generated from coulomb/repo-seed
Compare commits
11 Commits
f6787da8ef
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| a7eb35d29c | |||
| 88f70d9505 | |||
| eb067c494c | |||
| 8528005bdb | |||
| 82c7884103 | |||
| fa39883aec | |||
| 542d7c22be | |||
| afc0ef506b | |||
| f7f2502352 | |||
| c222b6cecc | |||
| ec20debc21 |
20
.claude/rules/agents.md
Normal file
20
.claude/rules/agents.md
Normal file
@@ -0,0 +1,20 @@
|
||||
## Kaizen Agents
|
||||
|
||||
Specialized agent personas available on demand via the state-hub MCP.
|
||||
|
||||
**Discover:** `list_kaizen_agents()` — returns all agents with name, description, category
|
||||
**Load:** `get_kaizen_agent("tdd-workflow")` — returns full instructions; read and follow them
|
||||
|
||||
Common agents:
|
||||
|
||||
| Agent | Category | When to use |
|
||||
|-------|----------|-------------|
|
||||
| `tdd-workflow` | testing | Step-by-step TDD8 workflow for any feature |
|
||||
| `code-refactoring` | quality | Code quality analysis and safe refactoring |
|
||||
| `test-maintenance` | testing | Diagnose and fix failing tests |
|
||||
| `requirements-engineering` | process | Prevent interface/mock mismatches upfront |
|
||||
| `keepaTodofile` | process | Maintain TODO.md during work |
|
||||
| `project-management` | process | Track status, determine next steps |
|
||||
| `datamodel-optimization` | quality | Optimize dataclasses and data structures |
|
||||
|
||||
All 17 agents: call `list_kaizen_agents()` for the full list.
|
||||
8
.claude/rules/architecture.md
Normal file
8
.claude/rules/architecture.md
Normal file
@@ -0,0 +1,8 @@
|
||||
## Architecture
|
||||
|
||||
<!-- TODO: Describe the key design decisions and component structure.
|
||||
Key modules, data flows, external integrations, state machines, etc. -->
|
||||
|
||||
## Quick Reference
|
||||
|
||||
`~/state-hub/mcp_server/TOOLS.md` — MCP tool reference
|
||||
50
.claude/rules/credential-routing.md
Normal file
50
.claude/rules/credential-routing.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# Credential and access routing
|
||||
|
||||
**Audience:** Codex, Claude Code, Grok, and custodian agents that call **llm-connect**
|
||||
for inference. Run this check **before** requesting secrets, API keys, SSH access,
|
||||
login tokens, or database passwords — in any repo, not only `ops-warden`.
|
||||
|
||||
ops-warden **issues SSH certificates only** (`warden sign`, `cert_command`). Every
|
||||
other credential need belongs to another subsystem. **Do not** message
|
||||
`ops-warden` on State Hub expecting a secret value; the reply is a pointer, not a key.
|
||||
|
||||
### Lookup (do this first)
|
||||
|
||||
```bash
|
||||
warden route find "<describe your need>" --json
|
||||
warden route show <catalog-id> --json
|
||||
```
|
||||
|
||||
Requires the `warden` CLI from `~/ops-warden` (`uv tool install .` or `uv run warden`).
|
||||
|
||||
| Agent runtime | How to orient |
|
||||
| --- | --- |
|
||||
| **Codex / Grok** (shell, HTTP State Hub) | `warden route` commands above; inbox `to_agent=feature-control` is for coordination, not secret vending |
|
||||
| **Claude Code** (MCP when available) | `get_domain_summary("custodian")` for workstreams; **still** use `warden route` for credential ownership |
|
||||
| **llm-connect** (inference service) | Never put secret retrieval in prompts; route custody to OpenBao/operator paths surfaced by `warden route` |
|
||||
|
||||
### Quick routing table
|
||||
|
||||
| I need… | Owner | ops-warden executes? |
|
||||
| --- | --- | --- |
|
||||
| SSH cert (`adm`/`agt`/`atm`) | ops-warden | **Yes** — `warden sign` |
|
||||
| API key, DB password, provider token | OpenBao (`railiance-platform`) | No — route only |
|
||||
| Login / OIDC / MFA | key-cape / Keycloak | No — route only |
|
||||
| Authorization decision | flex-auth | No — route only |
|
||||
| activity-core → issue-core emission | activity-core + issue-core | No — `warden route show activity-core-issue-sink` |
|
||||
| SSH tunnel | ops-bridge (+ `cert_command` from warden) | No — route only |
|
||||
|
||||
### Anti-patterns (do not do these)
|
||||
|
||||
- `POST /messages/` to `ops-warden` asking for `ISSUE_CORE_API_KEY`, `OPENROUTER_API_KEY`, etc.
|
||||
- Inventing `warden secret`, `warden login`, `warden bao`, `warden tunnel` — they do not exist
|
||||
- Pasting secrets into Git, State Hub, workplans, logs, or chat
|
||||
|
||||
### Other capabilities (reuse-surface)
|
||||
|
||||
Non-credential capabilities are usually discovered through **reuse-surface** federation
|
||||
(`reuse-surface` registry / `capability.*` indexes). Credential routing is inlined in
|
||||
every repo's agent instructions because it is high-frequency, high-risk, and easy to
|
||||
get wrong.
|
||||
|
||||
**Canon:** `~/ops-warden/wiki/CredentialRouting.md` · catalog `~/ops-warden/registry/routing/catalog.yaml`
|
||||
38
.claude/rules/first-session.md
Normal file
38
.claude/rules/first-session.md
Normal file
@@ -0,0 +1,38 @@
|
||||
## First Session Protocol
|
||||
|
||||
Triggered when `get_domain_summary("infotech")` shows **no workstreams**.
|
||||
The project is registered but work has not yet been structured.
|
||||
|
||||
**Step 1 — Read, don't write**
|
||||
- `~/the-custodian/canon/projects/infotech/project_charter_v0.1.md` — purpose, scope
|
||||
- `~/the-custodian/canon/projects/infotech/roadmap_v0.1.md` — planned phases
|
||||
- Scan repo root: README, directory structure, existing code or docs
|
||||
|
||||
**Step 2 — Survey in-progress work**
|
||||
Look for TODOs, open branches, half-finished files. Note done vs. started but incomplete.
|
||||
|
||||
**Step 3 — Propose workstreams to Bernd**
|
||||
Propose 1–3 workstreams — each a coherent strand, weeks to months, anchored to a
|
||||
roadmap phase. **Wait for approval before creating.**
|
||||
|
||||
**Step 4 — Create workplan file first, then DB record (ADR-001)**
|
||||
```
|
||||
workplans/FEATURE-WP-NNNN-<slug>.md ← write this first
|
||||
```
|
||||
Then register in the hub:
|
||||
```
|
||||
create_workstream(topic_id="f39fa2a3-c491-414c-a91b-b4c5fcc6139c", title="...", owner="...", description="...")
|
||||
create_task(workstream_id="<id>", title="...", priority="high|medium|low")
|
||||
```
|
||||
|
||||
**Step 5 — Record the setup**
|
||||
```
|
||||
add_progress_event(
|
||||
summary="First session: structured infotech into N workstreams, M tasks",
|
||||
event_type="milestone",
|
||||
topic_id="f39fa2a3-c491-414c-a91b-b4c5fcc6139c",
|
||||
detail={"workstreams": [...], "tasks_created": M}
|
||||
)
|
||||
```
|
||||
|
||||
<!-- Delete or archive this file once past first session -->
|
||||
8
.claude/rules/repo-boundary.md
Normal file
8
.claude/rules/repo-boundary.md
Normal file
@@ -0,0 +1,8 @@
|
||||
## Repo boundary
|
||||
|
||||
This repo owns **feature-control** only. It does not own:
|
||||
|
||||
<!-- TODO: List what belongs in adjacent repos, e.g.:
|
||||
- SSH key management → railiance-infra/
|
||||
- State hub code → state-hub/
|
||||
-->
|
||||
5
.claude/rules/repo-identity.md
Normal file
5
.claude/rules/repo-identity.md
Normal file
@@ -0,0 +1,5 @@
|
||||
**Purpose:** Open feature based multi-vendor, multi-tenant, multi-scope feature availability and provisioning engine.
|
||||
|
||||
**Domain:** infotech
|
||||
**Repo slug:** feature-control
|
||||
**Topic ID:** f39fa2a3-c491-414c-a91b-b4c5fcc6139c
|
||||
85
.claude/rules/session-protocol.md
Normal file
85
.claude/rules/session-protocol.md
Normal file
@@ -0,0 +1,85 @@
|
||||
## Session Protocol
|
||||
|
||||
Dev Hub (State Hub API): http://127.0.0.1:8000
|
||||
MCP server name in `~/.claude.json`: `dev-hub`
|
||||
|
||||
**Step 1 — Orient**
|
||||
|
||||
Read the offline-safe brief first — it works without a live hub connection:
|
||||
```bash
|
||||
cat .custodian-brief.md
|
||||
```
|
||||
Then call the MCP tool for richer cross-domain context when MCP tools are exposed:
|
||||
```
|
||||
get_domain_summary("infotech")
|
||||
```
|
||||
If MCP tools are unavailable in the current agent session, use the REST API:
|
||||
```bash
|
||||
curl -s "http://127.0.0.1:8000/state/summary" | python3 -m json.tool
|
||||
```
|
||||
If the hub is offline: `cd ~/state-hub && make api`
|
||||
|
||||
**Step 2 — Check inbox**
|
||||
With MCP tools:
|
||||
```
|
||||
get_messages(to_agent="feature-control", unread_only=True)
|
||||
```
|
||||
Mark read with `mark_message_read(message_id)`. Reply or act on coordination
|
||||
requests before proceeding.
|
||||
|
||||
Without MCP tools:
|
||||
```bash
|
||||
curl -s "http://127.0.0.1:8000/messages/?to_agent=feature-control&unread_only=true" \
|
||||
| python3 -m json.tool
|
||||
curl -s -X PATCH "http://127.0.0.1:8000/messages/<id>/read" \
|
||||
-H "Content-Type: application/json" -d '{}'
|
||||
```
|
||||
|
||||
**Step 3 — Scan workplans**
|
||||
```bash
|
||||
ls workplans/
|
||||
```
|
||||
For each file with `status: ready`, `active`, or `blocked`, note pending
|
||||
`wait`/`todo`/`progress` tasks.
|
||||
|
||||
**Step 4 — Present brief**
|
||||
|
||||
1. **Active workstreams** for `infotech` — title, task counts, blocking decisions
|
||||
2. **Pending tasks** from `workplans/` + any `[repo:feature-control]` hub tasks
|
||||
3. **Goal guidance** — if `goal_guidance` in summary:
|
||||
- `needs_workplan`: surface as top action — *"Repo goal '{title}' has no workplan yet"*
|
||||
- `alignment_warnings`: flag if active work is not aligned with current goal
|
||||
4. **Suggested next action** — highest-priority open item
|
||||
5. **SBOM status** — flag if `last_sbom_at` is unset for this repo
|
||||
|
||||
If no workstreams: follow First Session Protocol (`first-session.md`).
|
||||
|
||||
**During work:** `record_decision()` · `add_progress_event()` · `resolve_decision()`
|
||||
|
||||
> State Hub is a *read model*. Bootstrap tools (`create_workstream`, `create_task`)
|
||||
> are First Session Protocol only. Work structure belongs in repo files (ADR-001).
|
||||
|
||||
**Session close:**
|
||||
With MCP tools:
|
||||
```
|
||||
add_progress_event(summary="...", topic_id="f39fa2a3-c491-414c-a91b-b4c5fcc6139c", workstream_id="<uuid>")
|
||||
```
|
||||
Without MCP tools:
|
||||
```bash
|
||||
curl -s -X POST http://127.0.0.1:8000/progress/ \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"topic_id":"f39fa2a3-c491-414c-a91b-b4c5fcc6139c","workstream_id":"<uuid>","event_type":"note","summary":"what changed","author":"codex"}'
|
||||
```
|
||||
If workplan files were modified, ensure the local copy is up to date first:
|
||||
```bash
|
||||
git -C <repo_path> pull --ff-only
|
||||
cd ~/state-hub && make fix-consistency REPO=feature-control
|
||||
```
|
||||
For repos where implementation runs on a remote machine (e.g. CoulombCore),
|
||||
use the combined target which pulls before fixing:
|
||||
```bash
|
||||
cd ~/state-hub && make fix-consistency-remote REPO=feature-control
|
||||
```
|
||||
**C-15** (DB task ahead of file) is normal in multi-machine workflows — writeback
|
||||
will sync the file to match DB. **C-16** (repo behind remote) blocks all writes
|
||||
until you pull — intentional to prevent clobbering remote progress.
|
||||
19
.claude/rules/stack-and-commands.md
Normal file
19
.claude/rules/stack-and-commands.md
Normal file
@@ -0,0 +1,19 @@
|
||||
## Stack
|
||||
|
||||
<!-- TODO: Fill in language, frameworks, and key dependencies -->
|
||||
- **Language:**
|
||||
- **Key deps:**
|
||||
|
||||
## Dev Commands
|
||||
|
||||
```bash
|
||||
# TODO: Fill in the standard commands for this repo
|
||||
|
||||
# Install dependencies
|
||||
|
||||
# Run tests
|
||||
|
||||
# Lint / type check
|
||||
|
||||
# Build / package (if applicable)
|
||||
```
|
||||
40
.claude/rules/workplan-convention.md
Normal file
40
.claude/rules/workplan-convention.md
Normal file
@@ -0,0 +1,40 @@
|
||||
## Workplan Convention (ADR-001)
|
||||
|
||||
File location: `workplans/FEATURE-WP-NNNN-<slug>.md`
|
||||
ID prefix: `FEATURE-WP-`
|
||||
|
||||
Work items originate as files in this repo **before** being registered in the hub.
|
||||
|
||||
Canonical workplan/workstream frontmatter statuses are:
|
||||
`proposed`, `ready`, `active`, `blocked`, `backlog`, `finished`, `archived`.
|
||||
Use `proposed` for a newly drafted plan, `ready` after review against current
|
||||
repo state, and `finished` when implementation is complete. `stalled` and
|
||||
`needs_review` are derived health labels, not stored statuses.
|
||||
|
||||
Closed workplans may be moved to `workplans/archived/` with a completion-date
|
||||
prefix: `YYMMDD-FEATURE-WP-NNNN-<slug>.md`. The frontmatter id remains
|
||||
unchanged; the prefix is only for quick visual reference.
|
||||
|
||||
Small opportunistic tasks discovered during another session use **Ad Hoc Tasks**:
|
||||
`workplans/ADHOC-YYYY-MM-DD.md`, workstream slug `adhoc-YYYY-MM-DD`, and task ids
|
||||
`ADHOC-YYYY-MM-DD-T01`, `T02`, etc. Use adhocs only for low-risk work completed
|
||||
directly. Promote anything requiring analysis, design, approval, dependencies, or
|
||||
multiple planned phases into a normal workplan.
|
||||
|
||||
Ecosystem todos from other agents arrive as `[repo:feature-control]` hub tasks —
|
||||
visible at session start. Pick one up by creating the workplan file, then registering
|
||||
the workstream.
|
||||
|
||||
Task blocks use this shape:
|
||||
|
||||
```task
|
||||
id: FEATURE-WP-NNNN-T01
|
||||
status: wait | todo | progress | done | cancel
|
||||
priority: high | medium | low
|
||||
state_hub_task_id: "<uuid>" # written by fix-consistency — do not edit
|
||||
```
|
||||
|
||||
Status progression is `todo` → `progress` → `done`; use `wait` for waiting or
|
||||
blocked work and `cancel` for stopped work.
|
||||
|
||||
<!-- Ralph Loop rules and HEUREKA sequence: ~/.claude/CLAUDE.md — do not duplicate here -->
|
||||
@@ -1,8 +1,8 @@
|
||||
<!-- custodian-brief: generated by fix-consistency — do not edit manually -->
|
||||
# Custodian Brief — feature-control
|
||||
|
||||
**Domain:** helix_forge
|
||||
**Last synced:** 2026-06-14 19:42 UTC
|
||||
**Domain:** infotech
|
||||
**Last synced:** 2026-06-22 21:21 UTC
|
||||
**State Hub:** http://127.0.0.1:8000 *(adjust if running on a remote machine)*
|
||||
|
||||
## Active Workstreams
|
||||
@@ -13,6 +13,6 @@
|
||||
## MCP Orientation (when available)
|
||||
|
||||
If the state-hub MCP server is reachable, call:
|
||||
`get_domain_summary("helix_forge")`
|
||||
`get_domain_summary("infotech")`
|
||||
This provides richer cross-domain context.
|
||||
If the MCP call fails, use this file as your orientation source.
|
||||
|
||||
16
.repo-classification.yaml
Normal file
16
.repo-classification.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
repo_classification:
|
||||
standard: Repo Classification Standard
|
||||
version: '1.0'
|
||||
classified_at: '2026-06-22'
|
||||
classified_by: agent
|
||||
category: project
|
||||
domain: infotech
|
||||
secondary_domains: []
|
||||
capability_tags: []
|
||||
business_stake:
|
||||
- technology
|
||||
- product
|
||||
- operations
|
||||
business_mechanics:
|
||||
- coordination
|
||||
- operation
|
||||
67
AGENTS.md
67
AGENTS.md
@@ -4,7 +4,7 @@
|
||||
|
||||
**Purpose:** Open feature based multi-vendor, multi-tenant, multi-scope feature availability and provisioning engine.
|
||||
|
||||
**Domain:** helix_forge
|
||||
**Domain:** infotech
|
||||
**Repo slug:** feature-control
|
||||
**Topic ID:** `f39fa2a3-c491-414c-a91b-b4c5fcc6139c`
|
||||
**Workplan prefix:** `FEATURE-WP-`
|
||||
@@ -101,19 +101,62 @@ curl -s -X PATCH "http://127.0.0.1:8000/tasks/<task_id>" \
|
||||
|
||||
---
|
||||
|
||||
## Local Developer Workflow
|
||||
## Credential and access routing
|
||||
|
||||
This repository is documentation- and planning-focused (no source code, no traditional build/test/lint/install/run toolchain).
|
||||
**Audience:** Codex, Claude Code, Grok, and custodian agents that call **llm-connect**
|
||||
for inference. Run this check **before** requesting secrets, API keys, SSH access,
|
||||
login tokens, or database passwords — in any repo, not only `ops-warden`.
|
||||
|
||||
**Verification and development commands (add to future sessions as needed):**
|
||||
- Orient and review: `cat .custodian-brief.md` ; `cat INTENT.md SCOPE.md AGENTS.md README.md` ; `ls workplans/`
|
||||
- Check hub state (requires local state-hub API): use the curl commands documented in "State Hub Integration" and "Session Protocol" sections above.
|
||||
- After any workplan or doc changes: From `~/state-hub` checkout, run `make fix-consistency REPO=feature-control` (syncs markdown task statuses into hub DB, updates brief, populates state_hub_* IDs).
|
||||
- Update task status in workplan files (use search_replace or equivalent) then re-run fix-consistency.
|
||||
- Log required progress: `curl -s -X POST http://127.0.0.1:8000/progress/ ...` (see protocol).
|
||||
- To verify changes post-fix: Re-`cat .custodian-brief.md`, re-`ls workplans/`, re-check task statuses in files vs hub queries, confirm no drift.
|
||||
ops-warden **issues SSH certificates only** (`warden sign`, `cert_command`). Every
|
||||
other credential need belongs to another subsystem. **Do not** message
|
||||
`ops-warden` on State Hub expecting a secret value; the reply is a pointer, not a key.
|
||||
|
||||
No `make install`, `make test`, `make lint`, `make build`, or `make run` apply yet (pure docs repo). If implementation artifacts (e.g. OpenFeature wrappers, providers, or example code) are added later, define and document the appropriate commands here and in relevant workplans.
|
||||
### Lookup (do this first)
|
||||
|
||||
```bash
|
||||
warden route find "<describe your need>" --json
|
||||
warden route show <catalog-id> --json
|
||||
```
|
||||
|
||||
Requires the `warden` CLI from `~/ops-warden` (`uv tool install .` or `uv run warden`).
|
||||
|
||||
| Agent runtime | How to orient |
|
||||
| --- | --- |
|
||||
| **Codex / Grok** (shell, HTTP State Hub) | `warden route` commands above; inbox `to_agent=feature-control` is for coordination, not secret vending |
|
||||
| **Claude Code** (MCP when available) | `get_domain_summary("custodian")` for workstreams; **still** use `warden route` for credential ownership |
|
||||
| **llm-connect** (inference service) | Never put secret retrieval in prompts; route custody to OpenBao/operator paths surfaced by `warden route` |
|
||||
|
||||
### Quick routing table
|
||||
|
||||
| I need… | Owner | ops-warden executes? |
|
||||
| --- | --- | --- |
|
||||
| SSH cert (`adm`/`agt`/`atm`) | ops-warden | **Yes** — `warden sign` |
|
||||
| API key, DB password, provider token | OpenBao (`railiance-platform`) | No — route only |
|
||||
| Login / OIDC / MFA | key-cape / Keycloak | No — route only |
|
||||
| Authorization decision | flex-auth | No — route only |
|
||||
| activity-core → issue-core emission | activity-core + issue-core | No — `warden route show activity-core-issue-sink` |
|
||||
| SSH tunnel | ops-bridge (+ `cert_command` from warden) | No — route only |
|
||||
|
||||
### Anti-patterns (do not do these)
|
||||
|
||||
- `POST /messages/` to `ops-warden` asking for `ISSUE_CORE_API_KEY`, `OPENROUTER_API_KEY`, etc.
|
||||
- Inventing `warden secret`, `warden login`, `warden bao`, `warden tunnel` — they do not exist
|
||||
- Pasting secrets into Git, State Hub, workplans, logs, or chat
|
||||
|
||||
### Other capabilities (reuse-surface)
|
||||
|
||||
Non-credential capabilities are usually discovered through **reuse-surface** federation
|
||||
(`reuse-surface` registry / `capability.*` indexes). Credential routing is inlined in
|
||||
every repo's agent instructions because it is high-frequency, high-risk, and easy to
|
||||
get wrong.
|
||||
|
||||
**Canon:** `~/ops-warden/wiki/CredentialRouting.md` · catalog `~/ops-warden/registry/routing/catalog.yaml`
|
||||
|
||||
<!-- REPO-AGENTS-EXTENSIONS -->
|
||||
<!-- Append repo-specific agent instructions below this marker.
|
||||
The state-hub template sync preserves content after this line. -->
|
||||
|
||||
---
|
||||
|
||||
## Workplan Convention (ADR-001)
|
||||
|
||||
@@ -138,7 +181,7 @@ anything needing analysis, design, approval, dependencies, or multiple phases.
|
||||
id: FEATURE-WP-NNNN
|
||||
type: workplan
|
||||
title: "..."
|
||||
domain: helix_forge
|
||||
domain: infotech
|
||||
repo: feature-control
|
||||
status: proposed | ready | active | blocked | backlog | finished | archived
|
||||
owner: codex
|
||||
|
||||
12
CLAUDE.md
Normal file
12
CLAUDE.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# feature-control — Claude Code Instructions
|
||||
|
||||
@SCOPE.md
|
||||
@.claude/rules/repo-identity.md
|
||||
@.claude/rules/session-protocol.md
|
||||
@.claude/rules/first-session.md
|
||||
@.claude/rules/workplan-convention.md
|
||||
@.claude/rules/stack-and-commands.md
|
||||
@.claude/rules/architecture.md
|
||||
@.claude/rules/repo-boundary.md
|
||||
@.claude/rules/credential-routing.md
|
||||
@.claude/rules/agents.md
|
||||
76
docs/ConsumerBrief-FeatureControl.md
Normal file
76
docs/ConsumerBrief-FeatureControl.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# Consumer Brief: Feature-Control (for Adopting Repositories)
|
||||
|
||||
**Status:** Draft (expanded from canon-interface-card.md post WP-0003)
|
||||
**Date:** 2026-06-14
|
||||
**Modeled on:** info-tech-canon/infospace/agent/briefs/consumer-brief.template.md and interface-card.schema.yaml (per canon practices).
|
||||
**Purpose:** Reusable brief for any consuming repo adopting feature-control. Use in State Hub, ralph sessions, or as attachment to adoption workplans.
|
||||
|
||||
## Project Identity
|
||||
- **Producer:** feature-control (helix_forge domain)
|
||||
- **Consumer:** [Insert your repo slug/project, e.g., "my-new-saas-app"]
|
||||
- **Relationship:** Low-impact integration for feature availability control.
|
||||
|
||||
## Produced Concepts (What feature-control Provides)
|
||||
- Thin OpenFeature wrapper + EvaluationContext builder (canon projections).
|
||||
- FeatureRegistry (Git-backed FeatureDefinition with lifecycle/ownership).
|
||||
- Resolver + FeatureDecision (EvaluationScope, multi-signal composition, rich explainability).
|
||||
- LocalProvider (for dev/tests; extensible to real OF providers).
|
||||
- Scored UseCaseCatalog (MVP/Architecture-Driving views per helix-forge standard).
|
||||
- Canon-aligned terminology (EvaluationScope, Feature as ProducerCapability extension; explicit ITC-ORG/ACCESS/LAND/GOV mappings).
|
||||
- Pilots, examples, and adoption guide (for quick start).
|
||||
|
||||
## Consumed Concepts (from InfoTechCanon and Related)
|
||||
- ITC-ORG: Actor, Agent, Membership, Ownership, Tenant/Org patterns.
|
||||
- ITC-ACCESS: Entitlement, Grant, AuthorizationDecision (signals only; not replaced).
|
||||
- ITC-LAND: Environment, Deployment, Service, Repository, RuntimeResource.
|
||||
- ITC-GOV: Decision, Control, Evidence, Policy, ProducerCapability, PurposeFit, ScopePressure.
|
||||
- ITC-TaggingStandard: Feature categories.
|
||||
- ITC-TASK: Lifecycle reviews/remediation.
|
||||
- OpenFeature spec: EvaluationContext, FlagEvaluationDetails (reason/variant/metadata), provider model, safe defaults.
|
||||
- (See docs/canon-mapping.md for full table with ownership/gaps.)
|
||||
|
||||
## Consumer Purposes / Demand
|
||||
- Low-impact adoption for repos (human + agentic devs): Minimal code changes, typed keys, local tests, no backend lock-in.
|
||||
- Multi-scope control: Tenant, agent, environment, domain, etc. (via EvaluationScope).
|
||||
- Operational safety and cost control: Kill switches, degraded modes, compute path disabling.
|
||||
- Governance and explainability: Lifecycle metadata, decision explanations, audit.
|
||||
- Agent capability gating (with separate tool auth).
|
||||
- Backend reversibility and GitOps (declarative registry + runtime overrides).
|
||||
|
||||
## Scope Pressure / Fit
|
||||
- Current pain in consumer: [Insert: e.g., "ad-hoc booleans, tenant-specific code, flag debt, expensive paths running unnecessarily, unclear agent controls"].
|
||||
- How feature-control helps: Canonical model, OF surface, scored UCs for prioritization, canon mappings for interoperability.
|
||||
- Fit with consumer INTENT/SCOPE: [Insert mapping; e.g., "Your 'user can do X' maps to feature key 'your.domain.x'; tenant controls align with your multi-tenant model."]
|
||||
|
||||
## Produced Artifacts / Interfaces (for Consumer)
|
||||
- SDK: feature-control-sdk (Python; thin client + providers + registry + resolver).
|
||||
- Docs: AdoptionGuide.md, scored UCC, canon-mapping.md, mvp_pilot.py, sdk-examples/.
|
||||
- Registry baseline: features.json (Git-committed FeatureDefinitions).
|
||||
- Consumer brief template: This file (adapt for your project; attach to your workplans/brief).
|
||||
|
||||
## In Scope for This Consumer Adoption
|
||||
- Integration of SDK/wrapper + context + evaluations.
|
||||
- Feature registration and basic governance.
|
||||
- Local/dev adoption + pilot validation.
|
||||
- Mapping of your features to the scored UCC for MVP selection.
|
||||
|
||||
## Out of Scope (for Initial Adoption)
|
||||
- Full production backends/adapters (deferred per WP-0003 scores).
|
||||
- Deep entitlement self-service or complex approvals.
|
||||
- Non-Python implementations (adapt the concepts via OpenFeature).
|
||||
|
||||
## Open Questions / Risks for Consumer
|
||||
- [Insert project-specific: e.g., "How to export generated keys for our TypeScript frontend? Backend choice for production?"]
|
||||
- General: See WP-0003 open questions (backend, generated keys, etc.).
|
||||
|
||||
## Evidence / Next Steps
|
||||
- Pilot your adoption using docs/pilots/mvp_pilot.py (adapt for your UCs).
|
||||
- Create consumer workplan (e.g., "Adopt feature-control") with tasks from the AdoptionGuide.
|
||||
- Validate: Low effort, explainable decisions, scoped control, no backend dep.
|
||||
- Contribute back: New UCs, patterns, or canon extensions via State Hub.
|
||||
|
||||
**Attach this (customized) to your project's .custodian-brief.md, workplans, or adoption sessions for traceability.**
|
||||
|
||||
See the full FeatureControlAdoptionGuide.md for step-by-step instructions and the reusable agent prompt. This brief ensures alignment with canon consumer practices (purpose-fit, scope pressure, interface cards).
|
||||
|
||||
Ready for your specific project? Provide details and we'll customize/generate the artifacts.
|
||||
206
docs/FeatureControlAdoptionGuide.md
Normal file
206
docs/FeatureControlAdoptionGuide.md
Normal file
@@ -0,0 +1,206 @@
|
||||
# Feature-Control Adoption Guide for Consuming Repositories
|
||||
|
||||
**Status:** Draft (post WP-0003 MVP)
|
||||
**Date:** 2026-06-14
|
||||
**Audience:** Developers, architects, and AI agents integrating feature-control into new or existing projects (consuming repos).
|
||||
**Based on:** FEATURE-WP-0003 MVP implementation, scored UseCaseCatalog.md, canon-mapping.md, canon-interface-card.md (modeled on info-tech-canon consumer briefs), pilot examples, PRD/INTENT boundaries.
|
||||
|
||||
This guide provides a practical, step-by-step process for adopting the feature-control framework. It ensures low-impact integration, canon alignment (EvaluationScope, ITC-ORG/ACCESS/LAND/GOV mappings), and use of the scored use cases for prioritization.
|
||||
|
||||
## 1. Prerequisites and Orientation
|
||||
Before starting:
|
||||
- Read the core docs in this repo (or the feature-control package):
|
||||
- [INTENT.md](../INTENT.md): Stable intent, boundaries (OpenFeature-first, no auth/entitlement ownership, GitOps + runtime).
|
||||
- [specs/ProductRequirementsDocument.md](../specs/ProductRequirementsDocument.md): Requirements, data models, architecture.
|
||||
- [specs/UseCaseCatalog.md](../specs/UseCaseCatalog.md): Full catalog **with scoring applied per helix-forge UseCaseScoringStandard.md**. Use the summary table, MVP/Prototype/Architecture-Driving views to prioritize (e.g., high Value + low-moderate Cost for early adoption).
|
||||
- [docs/canon-mapping.md](../docs/canon-mapping.md): Explicit mappings (e.g., Feature → ProducerCapability extension; EvaluationScope → ITC-ORG Membership + ITC-LAND dims). Avoid redefining canon terms.
|
||||
- [docs/canon-interface-card.md](../docs/canon-interface-card.md): High-level consumer view (produced concepts, consumed ITC models, purposes, scope pressure).
|
||||
- [docs/pilots/mvp_pilot.py](../docs/pilots/mvp_pilot.py) and [docs/sdk-examples/](../docs/sdk-examples/): Concrete usage examples.
|
||||
- Understand key canon-aligned concepts:
|
||||
- **EvaluationScope / TargetingScope**: Replaces bare "scope" (platform, tenant, agent, etc.). Maps to Memberships + Landscape resources.
|
||||
- **FeatureDecision**: Rich (value, reason, source, scope, etc.) for explainability.
|
||||
- **Context**: Projection from ITC-ORG (actors/agents), ITC-LAND (services/envs), ITC-ACCESS signals.
|
||||
- Check your project's alignment with INTENT boundaries (mechanism over policy; overlay before mutation; capability-aware adapters).
|
||||
|
||||
**Read the brief for the target project** (`.custodian-brief.md`) and its AGENTS.md/INTENT.md to map your features to the scored UCC.
|
||||
|
||||
## 2. High-Level Adoption Flow (Based on Scored UCC)
|
||||
Follow the recommended workflow from the helix-forge standard (capture → normalize → classify → score → select → implement). Prioritize from the UCC summary:
|
||||
|
||||
**MVP Candidates (strong for first integration, per scoring):**
|
||||
- UC-A1: Adopt in new repo (core path; high user/business/strategic/proof value).
|
||||
- UC-A2: Local/test provider (high proof/learning; low effort).
|
||||
- UC-C1: Enable for tenant (multi-tenant control).
|
||||
- UC-D3: AI agent capability (agent-first class).
|
||||
- UC-E1: Disable compute-heavy per tenant (cost governance).
|
||||
- UC-E4: Emergency kill switch (operational safety).
|
||||
- UC-G1: Register with lifecycle (governance/hygiene).
|
||||
|
||||
**Supporting/Prototype:**
|
||||
- UC-G3: Explain decision (explainability core).
|
||||
- UC-H1: Provider switch (reversibility).
|
||||
|
||||
**Later/Enhancement:** Complex self-service, full analytics (lower urgency or higher cost per scores).
|
||||
|
||||
**Architecture Drivers (implement early for understanding, even if deferred):** Those with high Architecture Score (cross-repo, canon impact, policy, reuse, compute, observability) — e.g., A1, E1, D3, G1.
|
||||
|
||||
## 3. Step-by-Step Integration (Low-Impact, per UC-A1/A2)
|
||||
1. **Add the SDK**:
|
||||
- For Python projects: Add `feature-control-sdk` as a dependency (current: local via `pip install -e` from this repo's pyproject.toml; future: PyPI).
|
||||
- Minimal: Copy `src/feature_control_sdk/` into your project initially.
|
||||
- Optional: `openfeature-sdk` for real providers (backend-agnostic per design).
|
||||
|
||||
2. **Initialize the Client** (thin wrapper):
|
||||
```python
|
||||
from feature_control_sdk import FeatureControlClient, LocalProvider, FeatureRegistry, Resolver
|
||||
|
||||
client = FeatureControlClient(domain="your-service") # Optional OF domain
|
||||
```
|
||||
|
||||
3. **Set up for Dev/Tests (LocalProvider, no backend)**:
|
||||
```python
|
||||
local_values = {
|
||||
"your.domain.capability.feature": True, # Use canonical keys
|
||||
# Simulate overrides/signals
|
||||
"tenant:acme:your.feature": False,
|
||||
"kill:your.feature": False,
|
||||
}
|
||||
client.set_provider(LocalProvider(local_values))
|
||||
|
||||
# For rich feature-control logic (MVP mode, no full OF needed):
|
||||
reg = FeatureRegistry("features.json") # Git-committed baseline
|
||||
# (Populate from registry or hardcode for pilot)
|
||||
resolver = Resolver(reg, local_values)
|
||||
client.set_resolver(resolver)
|
||||
```
|
||||
|
||||
4. **Build Evaluation Context** (canon-aligned):
|
||||
Use the `_build_context` logic or manual dict. Project from your system's facts (users, tenants, agents, services):
|
||||
```python
|
||||
context = {
|
||||
"targeting_key": "user-123", # Per OF spec
|
||||
"actor_type": "human", # or "agent"
|
||||
"tenant_id": "acme",
|
||||
"domain_id": "your-domain",
|
||||
"agent_id": "my-agent-v1" if agent else None,
|
||||
"environment": "production",
|
||||
"service": "your-service",
|
||||
"roles": ["user"],
|
||||
"plan": "premium",
|
||||
# Signals
|
||||
"entitlement": True, # From your entitlement system (ITC-ACCESS)
|
||||
}
|
||||
```
|
||||
|
||||
5. **Evaluate Features** (standard OF surface + rich control):
|
||||
```python
|
||||
enabled = client.get_boolean_value(
|
||||
"your.domain.capability.feature", # Canonical key (from registry)
|
||||
default=False,
|
||||
context=context
|
||||
)
|
||||
# For rich explain (UC-G3):
|
||||
decision = client.explain("your.domain.capability.feature", False, context)
|
||||
print(decision.reason, decision.scope) # e.g., "tenant_policy", "tenant:acme"
|
||||
```
|
||||
|
||||
6. **Register Features (Governance, per UC-G1)**:
|
||||
- Maintain a `features.json` (or registry export) in Git as declarative baseline.
|
||||
- Example definition (matches PRD/UCC):
|
||||
```json
|
||||
{
|
||||
"feature_key": "your.domain.capability.feature",
|
||||
"name": "Your Capability",
|
||||
"description": "...",
|
||||
"owner": "your-team", # ITC-ORG
|
||||
"category": "release", # ITC-Tagging
|
||||
"default_value": false,
|
||||
"safe_fallback": false,
|
||||
"lifecycle_state": "active",
|
||||
"expected_lifetime": "long_lived",
|
||||
"tenant_configurable": true,
|
||||
"documentation": "docs/features/..."
|
||||
}
|
||||
```
|
||||
- Use `FeatureRegistry` to load/validate/register (enforces owner, temp review dates).
|
||||
- In consuming code: Import or discover keys (stub scanner for UC-A3).
|
||||
|
||||
7. **Test and Adopt**:
|
||||
- Use LocalProvider for unit/integration tests (deterministic, network-free; UC-A2).
|
||||
- Pilot your features using `docs/pilots/mvp_pilot.py` as template (adapt for your UCs).
|
||||
- Measure: Adoption effort (should be <1 small task), explainability, control without redeploys.
|
||||
- For real providers: Configure OF provider (e.g., Unleash adapter) behind the client (H1 support).
|
||||
|
||||
8. **Governance and Advanced**:
|
||||
- Enforce lifecycle in your registry (temp features get Tasks per ITC-TASK).
|
||||
- Use `explain()` for support/debug (UC-G3).
|
||||
- Audit changes (stub in pilot; expand per G4).
|
||||
- For agents: Pass `actor_type: "agent"` + `agent_id` in context (D3 support; still enforce tool auth per boundaries).
|
||||
|
||||
## 4. Mapping Your Project's Features
|
||||
- Review your project's INTENT/SCOPE/UCC (or equivalent).
|
||||
- Map to feature-control UCC: E.g., "user can do X" → feature key like `your.domain.x` (per FR-3 naming).
|
||||
- Score/prioritize using the standard (or copy from our scored UCC).
|
||||
- Start with high-MVP-fit: Adoption + 2-3 core controls (tenant/agent/compute/kill).
|
||||
- Register in your Git baseline; control via context (tenant_id for multi-tenant, agent_id for AI).
|
||||
|
||||
## 5. Common Pitfalls and Boundaries (from INTENT/PRD)
|
||||
- **Do not** use features for auth (FR-8): Always pair with your authz system.
|
||||
- **Do not** confuse with entitlement: Feature control composes but doesn't own (UC-F1).
|
||||
- Client-side never enforces security.
|
||||
- Start with local provider; add real backends later (backend-agnostic).
|
||||
- Commit `features.json`/registry to Git for GitOps baseline.
|
||||
|
||||
## 6. Validation and Next Steps
|
||||
- Run the adapted pilot: End-to-end for your MVP UCs.
|
||||
- Check: Decisions explainable? Controls per scope (no cross-tenant)? Tests without backend?
|
||||
- Metrics: Adoption time, decision coverage, compute savings.
|
||||
- If it fits: Proceed to production hardening (e.g., real providers, full audit, adapter contracts).
|
||||
- Report back: Update your project's docs/brief with adoption status. Consider contributing patterns back (e.g., new UCs or canon extensions).
|
||||
|
||||
## 7. Agent/AI Support Prompts and Skills
|
||||
**Reusable Prompt Template** (for Grok, Claude, Cursor, etc.; copy-paste into your agent):
|
||||
```
|
||||
You are an expert at adopting the feature-control framework (OpenFeature-based, canon-aligned multi-scope feature availability control from the feature-control repo).
|
||||
|
||||
Follow this exact step-by-step guide from docs/FeatureControlAdoptionGuide.md:
|
||||
[PASTE THE FULL GUIDE ABOVE]
|
||||
|
||||
For the current project (describe briefly: [e.g., "a new multi-tenant SaaS app in Python with user/engine/agent actors, compute-heavy features, need for tenant/agent controls"]):
|
||||
|
||||
1. Identify 5-10 candidate features from the project's scope/intent.
|
||||
2. Map them to the scored UseCaseCatalog.md (prioritize MVP/Architecture-Driving).
|
||||
3. Propose canonical feature keys (per naming convention).
|
||||
4. Generate the integration code: client setup, context builder (using canon projections), evaluations, registry definitions (in JSON), tests with LocalProvider.
|
||||
5. Create a simple pilot script adapted from mvp_pilot.py.
|
||||
6. Note any canon gaps or custom UCs.
|
||||
7. Ensure compliance with INTENT boundaries.
|
||||
|
||||
Output: Updated code diffs, new files (e.g., feature_flags.py, features.json, tests), and a brief adoption report referencing the scoring and canon-mapping.
|
||||
```
|
||||
|
||||
**Dedicated Skill/Agent Recommendation**:
|
||||
- **Yes, create one**: A "feature-control-adopter" skill or ralph-style prompt.
|
||||
- Example skill file (add to your agent's skills dir or `docs/skills/adopt-feature-control.md`):
|
||||
- Trigger: "adopt feature-control in this project" or "/adopt-fc".
|
||||
- Behavior: Load this guide + canon-mapping + scored UCC + pilot as context. Walk user/agent through steps, generate code, validate against acceptance.
|
||||
- For ralph-workplan users: Tie a consumer workplan (e.g., "Adopt feature-control") to this prompt.
|
||||
- Enhancement: Integrate with State Hub (e.g., new workplan for consumer adoption in a target repo, using get_domain_summary for context).
|
||||
- This repo can host the canonical version; consumers copy/adapt.
|
||||
|
||||
## 8. Gaps and Future Support (from WP-0003 Open Questions)
|
||||
- Full backend providers (Unleash/Flagsmith adapters) and production config.
|
||||
- Generated constants/key discovery (beyond stub).
|
||||
- Deeper entitlement integration and tenant self-service.
|
||||
- Full adapter contracts (for non-Python or custom backends).
|
||||
- Publishing the SDK (PyPI, versioning).
|
||||
- More pilots/examples for other languages/UCS.
|
||||
|
||||
**Next Step Recommendation**:
|
||||
- If you have a specific new project/repo in mind (e.g., "my-new-app"), tell me the path or details — we can run a guided adoption session using the prompt above, generate the exact files, and create a consumer workplan (e.g., MYAPP-WP-0001-adopt-feature-control).
|
||||
- Create a new workplan here (FEATURE-WP-0004-feature-control-adoption-toolkit) to formalize the guide, skill, and consumer brief.
|
||||
- Expand the canon-interface-card.md into a full ConsumerBrief.md (per info-tech-canon templates).
|
||||
|
||||
This makes feature-control immediately usable for new projects while providing the requested guides/prompts/skills. The MVP gives a working foundation; we can iterate based on real adoption feedback.
|
||||
|
||||
Ready to proceed with a specific project or create the new artifacts? Provide details! (We'll log progress and sync via State Hub.)
|
||||
50
docs/pilots/mvp-pilot-report.md
Normal file
50
docs/pilots/mvp-pilot-report.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# MVP Pilot Validation Report (FEATURE-WP-0003-T06)
|
||||
|
||||
**Date:** 2026-06-19
|
||||
**Pilot:** `docs/pilots/mvp_pilot.py`
|
||||
**Tests:** `tests/test_registry_resolver.py`, `tests/test_sdk_wrapper.py` (incl. UC-H1)
|
||||
|
||||
## Scope
|
||||
|
||||
End-to-end validation of the WP-0003 MVP against the scored UseCaseCatalog MVP selection.
|
||||
|
||||
## Use cases exercised
|
||||
|
||||
| UC | Description | Result |
|
||||
|----|-------------|--------|
|
||||
| UC-G1 | Register with lifecycle | Pass — registry validates owner, temp review_date |
|
||||
| UC-A1/A2 | Adopt with wrapper + local provider | Pass — thin client + LocalProvider, no backend |
|
||||
| UC-C1 | Tenant enable | Pass — `tenant.preview` scoped to `acme` vs `globex` |
|
||||
| UC-D3 | Agent capability | Pass — `agent.extract` evaluated with agent context |
|
||||
| UC-E1 | Compute disable per tenant | Pass — `compute.heavy_ocr` disabled for tenant |
|
||||
| UC-E4 | Emergency kill switch | Pass — kill signal overrides tenant/default at runtime |
|
||||
| UC-G3 | Explain decision | Pass — `client.explain()` returns reason/source/scope |
|
||||
| UC-H1 | Provider switch | Pass — `test_h1_provider_switch_without_business_code_change` |
|
||||
|
||||
## Observations
|
||||
|
||||
- **Adoption effort:** Single-script pilot; a consuming repo can integrate in one small task using the SDK + LocalProvider pattern (aligns with UC-A1 scoring).
|
||||
- **Explainability:** Decisions include `reason`, `source`, `scope` — sufficient for MVP governance (UC-G3).
|
||||
- **Runtime control:** Kill switch and tenant overrides applied without redeploy (local values mutated in-process).
|
||||
- **Compute savings:** Pilot demonstrates disable path; real savings measurement deferred to production adapter work.
|
||||
- **Canon alignment:** Evaluation uses tenant/agent context dimensions consistent with `docs/canon-mapping.md` (EvaluationScope).
|
||||
|
||||
## Fit vs scored catalog
|
||||
|
||||
The MVP UCs selected in WP-0003 (A1, C1, D3, E1, E4, G1, G3, H1) are all demonstrated. Deferred items from the catalog remain appropriate for follow-on work:
|
||||
|
||||
- Full tenant self-service (higher cost/risk)
|
||||
- Experimentation analytics
|
||||
- Complex approval workflows
|
||||
- Production backend adapters (Unleash/Flagsmith/flagd)
|
||||
|
||||
No catalog adjustments required for the MVP boundary.
|
||||
|
||||
## Ready for next workplan
|
||||
|
||||
Pilot and automated tests satisfy T06 acceptance. Recommended follow-ons (per WP-0004 Production Hardening section):
|
||||
|
||||
1. Real OpenFeature provider adapters
|
||||
2. Entitlement signal integration depth
|
||||
3. SDK packaging (PyPI) and multi-language examples
|
||||
4. Adoption validation in a real consuming repository
|
||||
112
docs/pilots/mvp_pilot.py
Normal file
112
docs/pilots/mvp_pilot.py
Normal file
@@ -0,0 +1,112 @@
|
||||
"""
|
||||
MVP Pilot script for WP-0003 T06.
|
||||
|
||||
Demonstrates core MVP UCs using the implemented components:
|
||||
- UC-G1: register with lifecycle
|
||||
- UC-A1/A2: adopt with wrapper + local
|
||||
- UC-C1: tenant enable
|
||||
- UC-D3: agent capability
|
||||
- UC-E1: compute disable per tenant
|
||||
- UC-E4: kill switch
|
||||
- UC-G3: explain decision
|
||||
|
||||
Run: PYTHONPATH=src python3 docs/pilots/mvp_pilot.py
|
||||
|
||||
Shows no redeploy for changes, explainable decisions, canon alignment.
|
||||
"""
|
||||
|
||||
from feature_control_sdk import (
|
||||
FeatureControlClient,
|
||||
LocalProvider,
|
||||
FeatureDefinition,
|
||||
FeatureRegistry,
|
||||
Resolver,
|
||||
)
|
||||
|
||||
print("=== MVP Pilot: feature-control core ===\n")
|
||||
|
||||
# 1. Registry (UC-G1)
|
||||
reg = FeatureRegistry("/tmp/features.json") # "git" baseline
|
||||
reg.register(FeatureDefinition(
|
||||
feature_key="compute.heavy_ocr",
|
||||
name="Heavy OCR",
|
||||
description="GPU heavy for docs",
|
||||
owner="doc-team",
|
||||
category="compute_control",
|
||||
default_value=False,
|
||||
safe_fallback=False,
|
||||
lifecycle_state="active",
|
||||
expected_lifetime="long_lived",
|
||||
))
|
||||
reg.register(FeatureDefinition(
|
||||
feature_key="agent.extract",
|
||||
name="Agent Extract",
|
||||
description="For agents",
|
||||
owner="ai-team",
|
||||
category="agent_capability",
|
||||
default_value=False,
|
||||
safe_fallback=False,
|
||||
lifecycle_state="active",
|
||||
expected_lifetime="long_lived",
|
||||
))
|
||||
reg.register(FeatureDefinition(
|
||||
feature_key="tenant.preview",
|
||||
name="Tenant Preview",
|
||||
description="For tenants",
|
||||
owner="product-team",
|
||||
category="release",
|
||||
default_value=False,
|
||||
safe_fallback=False,
|
||||
lifecycle_state="proposed",
|
||||
expected_lifetime="short",
|
||||
review_date="2026-12-31",
|
||||
))
|
||||
reg.save()
|
||||
print("Registered features (UC-G1 satisfied):", reg.keys())
|
||||
|
||||
# 2. Local values + resolver for control logic
|
||||
local_values = {
|
||||
"compute.heavy_ocr": False, # default
|
||||
"agent.extract": False,
|
||||
"tenant.preview": True,
|
||||
"kill:compute.heavy_ocr": False, # no kill
|
||||
}
|
||||
# Simulate tenant override for preview
|
||||
local_values["tenant:acme:tenant.preview"] = True
|
||||
|
||||
resolver = Resolver(reg, local_values)
|
||||
|
||||
# 3. Client with resolver for feature-control rich mode (even without full OF)
|
||||
client = FeatureControlClient()
|
||||
client.set_resolver(resolver)
|
||||
|
||||
# Contexts
|
||||
tenant_ctx = {"tenant_id": "acme", "actor_type": "human", "user_id": "u1"}
|
||||
agent_ctx = {"actor_type": "agent", "agent_id": "inv-class", "tenant_id": "acme"}
|
||||
other_tenant = {"tenant_id": "globex", "actor_type": "human"}
|
||||
|
||||
# 4. Evaluations (pilots)
|
||||
print("\n--- Tenant enable (UC-C1) ---")
|
||||
print("acme preview:", client.get_boolean_value("tenant.preview", False, tenant_ctx))
|
||||
print("globex preview:", client.get_boolean_value("tenant.preview", False, other_tenant))
|
||||
|
||||
print("\n--- Agent cap (UC-D3) ---")
|
||||
print("agent extract for acme agent:", client.get_boolean_value("agent.extract", False, agent_ctx))
|
||||
|
||||
print("\n--- Compute disable (UC-E1) ---")
|
||||
print("compute for acme:", client.get_boolean_value("compute.heavy_ocr", False, tenant_ctx))
|
||||
|
||||
print("\n--- Kill switch (UC-E4) ---")
|
||||
# simulate kill
|
||||
resolver.values["kill:compute.heavy_ocr"] = True
|
||||
print("compute with kill for acme:", client.get_boolean_value("compute.heavy_ocr", False, tenant_ctx))
|
||||
|
||||
print("\n--- Explain (UC-G3) ---")
|
||||
decision = client.explain("tenant.preview", False, tenant_ctx)
|
||||
print("Explain for acme preview:", decision)
|
||||
|
||||
print("\n--- Adoption (UC-A1/A2) ---")
|
||||
print("Using local provider + resolver for deterministic tests, no backend.")
|
||||
|
||||
print("\nPilot complete. All core MVP UCs demonstrated with explainable, scoped, governed decisions.")
|
||||
print("No redeploy needed (local values changed at runtime).")
|
||||
65
docs/prompts/adopt-feature-control.md
Normal file
65
docs/prompts/adopt-feature-control.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# Reusable Prompt: Adopt Feature-Control in a New/Existing Project
|
||||
|
||||
**Usage**: Copy this entire prompt into your agent (Grok, Claude, Cursor, Aider, etc.) at the start of an adoption session. Replace placeholders in [brackets]. Follow exactly; reference the artifacts in this feature-control repo.
|
||||
|
||||
```
|
||||
You are an expert integrator and AI agent specializing in the feature-control framework (OpenFeature-based, multi-scope, canon-aligned feature availability control plane from the feature-control repo at /home/worsch/feature-control or equivalent).
|
||||
|
||||
Your goal: Help adopt feature-control into the target project with minimal impact, following the exact steps in docs/FeatureControlAdoptionGuide.md (created post-WP-0003 MVP). Ensure alignment with INTENT.md, the scored UseCaseCatalog.md (per helix-forge UseCaseScoringStandard), docs/canon-mapping.md, and docs/canon-interface-card.md.
|
||||
|
||||
**Exact Process (do not skip or reorder):**
|
||||
|
||||
1. **Orient and Review**:
|
||||
- Read and internalize: INTENT.md, specs/ProductRequirementsDocument.md, specs/UseCaseCatalog.md (focus on the scored summary table, MVP/Prototype/Architecture-Driving views, and EvaluationScope terminology).
|
||||
- Read: docs/canon-mapping.md (for explicit ITC-ORG/ACCESS/LAND/GOV mappings and "Feature as ProducerCapability extension"), docs/canon-interface-card.md, docs/pilots/mvp_pilot.py, and docs/sdk-examples/.
|
||||
- Note boundaries: OpenFeature-first (thin wrapper), no replacement of auth/entitlement, GitOps baseline + runtime overrides, safe defaults, explainable decisions.
|
||||
|
||||
2. **Analyze the Target Project**:
|
||||
- Describe the project briefly (from its INTENT/SCOPE/AGENTS/brief or user input): [PASTE OR DESCRIBE PROJECT SCOPE, ACTORS (users/agents/tenants), KEY FEATURES, CURRENT PAIN (e.g., hard-coded flags, compute waste, agent controls)].
|
||||
- Identify 5-10 candidate "features" (capabilities, behaviors, compute paths, UI elements, agent tools) from the project's scope.
|
||||
- Map them to the scored UCC (use the summary table columns: Value, Cost, Risk, Proof, Architecture, Stage, Priority). Prioritize high-Value + acceptable Cost/Risk for MVP (e.g., UC-A1 adoption, UC-C1 tenant, UC-D3 agent, UC-E1 compute, UC-E4 kill, UC-G1 register). Flag Architecture-Drivers explicitly.
|
||||
|
||||
3. **Design the Integration**:
|
||||
- Propose canonical feature keys (per FR-3: <domain>.<capability>.<feature>[.<mode>], e.g., "mail.dispatch.new_renderer").
|
||||
- Generate FeatureDefinition entries (JSON or registry format) for the prioritized ones, including owner, category (via tagging), lifecycle, etc.
|
||||
- Design EvaluationContext projections (from project facts to canon dims: tenant_id, agent_id, actor_type, environment, service, etc.).
|
||||
|
||||
4. **Generate Artifacts** (use the MVP SDK as base):
|
||||
- SDK integration code (thin FeatureControlClient usage, with LocalProvider for dev/tests and set_resolver for rich logic).
|
||||
- Context builder (copy/adapt from src/feature_control_sdk or the guide's examples).
|
||||
- features.json or registry baseline (declarative, Git-committed).
|
||||
- Tests using LocalProvider (deterministic, network-free).
|
||||
- Adapted pilot script (based on docs/pilots/mvp_pilot.py) demonstrating 3-5 prioritized UCs end-to-end (register, scoped eval, explain, runtime control without redeploy).
|
||||
- Any needed updates to the project's AGENTS.md, docs, or brief.
|
||||
|
||||
5. **Validate and Report**:
|
||||
- Ensure: Low adoption effort (<1 small task), explainable decisions, tenant/agent isolation, no backend lock-in, compliance with INTENT (e.g., client flags never auth).
|
||||
- Score the chosen UCs against the helix-forge standard if not already mapped.
|
||||
- Produce a brief adoption report: What was implemented, fit vs. scored catalog, open questions/gaps, next steps (e.g., real providers, new workplan).
|
||||
- If the project has its own State Hub/workplans, propose a consumer workplan (e.g., "Adopt feature-control") with tasks tied to the UCs.
|
||||
|
||||
**Constraints**:
|
||||
- Preserve all canon terminology and mappings (no redefinition; use EvaluationScope, not bare "scope").
|
||||
- Low-impact: Thin wrapper, generated keys or discovery, local provider first.
|
||||
- Output only diffs, new files, code, and the report. Use the SDK code from src/ as the reference implementation.
|
||||
- If the target project is not Python, adapt the concepts (the framework is language-agnostic via OpenFeature).
|
||||
|
||||
Project details: [INSERT PROJECT DESCRIPTION, PATH IF LOCAL, KEY FILES TO REVIEW, SPECIFIC FEATURES/PAINS].
|
||||
|
||||
Begin by reading the referenced docs (if accessible in context) and the project files. Output the plan, then the generated artifacts.
|
||||
```
|
||||
|
||||
**Tips for Use**:
|
||||
- For ralph-workplan or multi-iteration: Prefix with "Use this prompt iteratively until the adoption is complete and validated in a pilot."
|
||||
- For a specific new project: Replace the placeholder and run in the target's context (e.g., via Cursor or a subagent).
|
||||
- Extend with project-specific canon mappings if needed.
|
||||
|
||||
This prompt + the AdoptionGuide.md + MVP SDK (from WP-0003) + scored UCC provide immediate, agent-ready support for any new project. The canon-interface-card.md can be expanded into a full ConsumerBrief.md for the target (modeled on info-tech-canon templates).
|
||||
|
||||
**Recommended Next**:
|
||||
- If you name the new project/repo (e.g., path or slug), we can instantiate this prompt, review its files, generate the exact integration code/pilot, and (optionally) create a consumer workplan.
|
||||
- Create a dedicated skill (e.g., in your .grok/skills or .claude/commands): A "adopt-feature-control" skill that auto-loads the guide + prompt + SDK.
|
||||
- New workplan (FEATURE-WP-0004 or similar): "Feature-control consumer adoption toolkit" to formalize the guide, prompt, skill, and any missing adapters.
|
||||
- Publish the SDK (update pyproject, add to PyPI) for easier consumption.
|
||||
|
||||
We are ready for MVP adoption in new projects today. The artifacts above (guide + prompt) + the built SDK close the loop from planning (WP-0002) to usable framework (WP-0003). Let me know the new project or next artifact to create! (We'll sync via State Hub.)
|
||||
56
docs/sdk-examples/basic_usage.py
Normal file
56
docs/sdk-examples/basic_usage.py
Normal file
@@ -0,0 +1,56 @@
|
||||
"""
|
||||
Basic usage example for feature-control-sdk.
|
||||
|
||||
This demonstrates the thin wrapper + local provider for development.
|
||||
|
||||
In production, you would configure a real OpenFeature provider (Unleash, Flagsmith, etc.)
|
||||
behind the scenes. The consuming repo only sees standard OpenFeature calls.
|
||||
|
||||
See:
|
||||
- specs/UseCaseCatalog.md (UC-A1, UC-A2)
|
||||
- docs/canon-mapping.md for context projection from canon models.
|
||||
"""
|
||||
|
||||
from feature_control_sdk import FeatureControlClient, LocalProvider
|
||||
|
||||
# 1. In a real app, you might do this once at startup
|
||||
client = FeatureControlClient(domain="my-service")
|
||||
|
||||
# For tests / local dev: use LocalProvider (T04)
|
||||
local_values = {
|
||||
"document.ocr.compute_heavy_path": False,
|
||||
"agent.invoice_classifier.extract_recipient": True,
|
||||
"tenant.preview.feature": "variant-a",
|
||||
}
|
||||
client.set_provider(LocalProvider(local_values))
|
||||
|
||||
# 2. Evaluation context (built from canon facts: actor, tenant, etc.)
|
||||
# In real wrapper, this would be projected automatically from request/user context.
|
||||
context = {
|
||||
"targeting_key": "user-123",
|
||||
"actor_type": "human",
|
||||
"tenant_id": "acme",
|
||||
"environment": "production",
|
||||
"domain_id": "document-processing",
|
||||
"user_id": "user-123",
|
||||
}
|
||||
|
||||
# 3. Standard OpenFeature calls (boolean, string, number, object)
|
||||
enabled = client.get_boolean_value(
|
||||
"document.ocr.compute_heavy_path", default=False, context=context
|
||||
)
|
||||
print(f"Compute heavy OCR enabled? {enabled}") # False (from local)
|
||||
|
||||
agent_cap = client.get_boolean_value(
|
||||
"agent.invoice_classifier.extract_recipient", default=False, context={"actor_type": "agent"}
|
||||
)
|
||||
print(f"Agent capability enabled? {agent_cap}") # True
|
||||
|
||||
variant = client.get_string_value("tenant.preview.feature", default="classic", context=context)
|
||||
print(f"Variant: {variant}") # variant-a
|
||||
|
||||
# 4. Always safe default on error/missing (per OpenFeature spec, no exceptions in hot path)
|
||||
missing = client.get_boolean_value("does.not.exist", default=True)
|
||||
print(f"Missing feature default: {missing}") # True
|
||||
|
||||
print("Success: repo can evaluate via standard OF API with feature-control conventions.")
|
||||
34
pyproject.toml
Normal file
34
pyproject.toml
Normal file
@@ -0,0 +1,34 @@
|
||||
[build-system]
|
||||
requires = ["setuptools>=61.0"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "feature-control-sdk"
|
||||
version = "0.1.0"
|
||||
description = "Thin organization wrapper and local provider for OpenFeature in feature-control"
|
||||
authors = [{name = "feature-control initiative"}]
|
||||
readme = "README.md"
|
||||
license = {text = "MIT"}
|
||||
requires-python = ">=3.9"
|
||||
dependencies = [
|
||||
"openfeature-sdk>=0.1.0", # official OpenFeature Python SDK
|
||||
]
|
||||
classifiers = [
|
||||
"Programming Language :: Python :: 3",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
]
|
||||
|
||||
[project.optional-dependencies]
|
||||
dev = [
|
||||
"pytest",
|
||||
"ruff",
|
||||
]
|
||||
|
||||
[tool.setuptools.packages.find]
|
||||
where = ["src"]
|
||||
|
||||
[tool.ruff]
|
||||
line-length = 88
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
testpaths = ["tests"]
|
||||
12
registry/README.md
Normal file
12
registry/README.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Capability Registry
|
||||
|
||||
Markdown-first capability index for federation and reuse planning.
|
||||
|
||||
## Authoring
|
||||
|
||||
1. Copy a capability entry template (see reuse-surface `templates/capability-entry.template.md`).
|
||||
2. Add the row to `indexes/capabilities.yaml`.
|
||||
3. Run `reuse-surface validate` from a checkout with the CLI installed.
|
||||
4. Merge to `main` and verify publish with `reuse-surface establish --publish-check`.
|
||||
|
||||
Federation contract: reuse-surface `docs/RegistryFederation.md`.
|
||||
138
registry/capabilities/capability.feature-control.evaluate.md
Normal file
138
registry/capabilities/capability.feature-control.evaluate.md
Normal file
@@ -0,0 +1,138 @@
|
||||
---
|
||||
id: capability.feature-control.evaluate
|
||||
name: Feature Availability Evaluation
|
||||
summary: Evaluate whether a feature is active, hidden, disabled, or unavailable for a subject in context.
|
||||
owner: feature-control
|
||||
status: draft
|
||||
domain: helix_forge
|
||||
tags:
|
||||
- feature-control
|
||||
- evaluation
|
||||
- sdk
|
||||
|
||||
maturity:
|
||||
discovery:
|
||||
current: D5
|
||||
target: D7
|
||||
confidence: medium
|
||||
rationale: >
|
||||
Concrete use cases and research references are documented in the maturity
|
||||
standard example and feature-control domain work.
|
||||
availability:
|
||||
current: A4
|
||||
target: A6
|
||||
confidence: medium
|
||||
rationale: >
|
||||
SDK and service API artifacts exist in the feature-control repository.
|
||||
Managed platform operation is the natural target for multi-tenant reuse.
|
||||
|
||||
external_evidence:
|
||||
completeness:
|
||||
level: C3
|
||||
name: Functional Core
|
||||
confidence: medium
|
||||
basis: scope_vs_intent_and_consumer_expectations
|
||||
satisfied_expectations:
|
||||
- tenant-level feature evaluation
|
||||
- user-level feature evaluation
|
||||
- machine-readable decision result
|
||||
broken_expectations:
|
||||
- no agent-specific rule simulation
|
||||
- no bulk import/export of rules
|
||||
out_of_scope_expectations:
|
||||
- billing entitlement ownership
|
||||
- authorization policy enforcement
|
||||
reliability:
|
||||
level: R3
|
||||
name: Usable
|
||||
confidence: medium
|
||||
basis: consumer_quality_signals
|
||||
known_reliability_risks:
|
||||
- unclear timeout behavior under heavy load
|
||||
- limited diagnostics for complex tenant rule conflicts
|
||||
|
||||
discovery:
|
||||
intent: >
|
||||
Support controlled feature availability across installations, tenants,
|
||||
domains, groups, users, and agents.
|
||||
includes:
|
||||
- feature decision evaluation
|
||||
- context-aware targeting
|
||||
- explainable decision result
|
||||
excludes:
|
||||
- user authorization
|
||||
- billing entitlement ownership
|
||||
- UI rendering
|
||||
assumptions:
|
||||
- subject and tenant context can be resolved by adjacent capabilities
|
||||
use_cases:
|
||||
- ucc.feature-control.tenant-toggle
|
||||
- ucc.feature-control.agent-disable
|
||||
- ucc.feature-control.domain-rollout
|
||||
research_memos:
|
||||
- specs/CapabilityMaturityStandard.md
|
||||
|
||||
availability:
|
||||
current_level: A4
|
||||
target_level: A6
|
||||
current_artifacts:
|
||||
- feature-control/packages/feature-control-sdk
|
||||
- feature-control/services/feature-control-api
|
||||
target_artifacts:
|
||||
- feature-control/charts/feature-control
|
||||
- feature-control/platform/feature-control-service
|
||||
consumption_modes:
|
||||
- SDK
|
||||
- service API
|
||||
- managed platform service
|
||||
|
||||
relations:
|
||||
depends_on:
|
||||
- capability.identity.vocabulary-canonicalize
|
||||
supports:
|
||||
- capability.registry.register
|
||||
related_to:
|
||||
- capability.feature-control.rollout
|
||||
- capability.feature-control.visibility
|
||||
|
||||
evidence:
|
||||
documentation:
|
||||
- specs/CapabilityMaturityStandard.md
|
||||
tests: []
|
||||
consumer_feedback: []
|
||||
bug_reports: []
|
||||
incidents: []
|
||||
|
||||
consumer_guidance:
|
||||
recommended_for:
|
||||
- application integration through SDK or service API
|
||||
- tenant-aware feature gating in helix_forge products
|
||||
not_recommended_for:
|
||||
- authorization decisions
|
||||
- billing entitlement ownership
|
||||
- assuming agent-specific simulation without checking current scope
|
||||
known_limitations:
|
||||
- bulk rule management is not yet covered
|
||||
- agent-specific simulation remains a known gap
|
||||
---
|
||||
|
||||
# Feature Availability Evaluation
|
||||
|
||||
## Overview
|
||||
|
||||
This capability evaluates whether a feature should be available for a subject in
|
||||
a given context. It is the primary implementation-ready example in the sample
|
||||
registry and demonstrates a D5/A4/C3/R3 vector.
|
||||
|
||||
## Current reuse mode
|
||||
|
||||
Consumers can integrate through SDK or service API artifacts in the
|
||||
feature-control repository. This is implementation reuse (A4), not just planning
|
||||
metadata.
|
||||
|
||||
## Comparison notes
|
||||
|
||||
Compared with `capability.registry.register`, this entry is far stronger on
|
||||
availability and external evidence. Compared with
|
||||
`capability.identity.vocabulary-canonicalize`, it is stronger on delivery mode
|
||||
and weaker on cross-domain generalization.
|
||||
111
registry/capabilities/capability.feature-control.rollout.md
Normal file
111
registry/capabilities/capability.feature-control.rollout.md
Normal file
@@ -0,0 +1,111 @@
|
||||
---
|
||||
id: capability.feature-control.rollout
|
||||
name: Feature Rollout Control
|
||||
summary: Gradually expose features to subjects across tenants, domains, groups, or cohorts using rollout rules and staged availability.
|
||||
owner: feature-control
|
||||
status: draft
|
||||
domain: helix_forge
|
||||
tags:
|
||||
- feature-control
|
||||
- rollout
|
||||
- planning
|
||||
|
||||
maturity:
|
||||
discovery:
|
||||
current: D4
|
||||
target: D6
|
||||
confidence: medium
|
||||
rationale: >
|
||||
Rollout is a distinct bounded behavior from single-point evaluation, with
|
||||
research references in the feature-control domain and maturity standard.
|
||||
availability:
|
||||
current: A2
|
||||
target: A4
|
||||
confidence: low
|
||||
rationale: >
|
||||
Rollout logic may exist in source modules but is not yet consistently
|
||||
exposed as a standalone SDK or API surface distinct from evaluate.
|
||||
|
||||
external_evidence:
|
||||
completeness:
|
||||
level: C2
|
||||
name: Partial
|
||||
confidence: low
|
||||
basis: scope_vs_intent_and_consumer_expectations
|
||||
satisfied_expectations:
|
||||
- rollout concepts documented adjacent to feature evaluation
|
||||
broken_expectations:
|
||||
- no dedicated rollout artifact called out separately from evaluate
|
||||
- percentage and cohort rollout variants not indexed independently
|
||||
out_of_scope_expectations:
|
||||
- billing-driven entitlements
|
||||
reliability:
|
||||
level: R1
|
||||
name: Fragile
|
||||
confidence: low
|
||||
basis: consumer_quality_signals
|
||||
known_reliability_risks:
|
||||
- rollout behavior may be conflated with evaluate in consumer mental models
|
||||
|
||||
discovery:
|
||||
intent: >
|
||||
Control how features become available over time and across cohorts without
|
||||
conflating rollout policy with authorization or billing.
|
||||
includes:
|
||||
- staged rollout rules
|
||||
- cohort and context targeting for rollout
|
||||
- explainable rollout state
|
||||
excludes:
|
||||
- one-time feature evaluation only
|
||||
- authorization decisions
|
||||
- billing entitlements
|
||||
assumptions:
|
||||
- feature evaluation capability exists for final availability decisions
|
||||
use_cases:
|
||||
- ucc.feature-control.domain-rollout
|
||||
research_memos:
|
||||
- specs/CapabilityMaturityStandard.md
|
||||
|
||||
availability:
|
||||
current_level: A2
|
||||
target_level: A4
|
||||
current_artifacts:
|
||||
- feature-control/packages/feature-control-sdk
|
||||
target_artifacts:
|
||||
- feature-control/services/feature-control-api
|
||||
consumption_modes:
|
||||
- source module
|
||||
- SDK
|
||||
|
||||
relations:
|
||||
depends_on:
|
||||
- capability.feature-control.evaluate
|
||||
supports: []
|
||||
related_to:
|
||||
- capability.feature-control.visibility
|
||||
|
||||
evidence:
|
||||
documentation:
|
||||
- specs/CapabilityMaturityStandard.md
|
||||
tests: []
|
||||
consumer_feedback: []
|
||||
bug_reports: []
|
||||
incidents: []
|
||||
|
||||
consumer_guidance:
|
||||
recommended_for:
|
||||
- planning staged feature exposure separate from binary evaluation
|
||||
not_recommended_for:
|
||||
- simple on/off evaluation without rollout semantics
|
||||
- entitlement or billing ownership
|
||||
known_limitations:
|
||||
- distinguish carefully from capability.feature-control.evaluate
|
||||
---
|
||||
|
||||
# Feature Rollout Control
|
||||
|
||||
## Overview
|
||||
|
||||
Rollout governs how availability changes over time and across cohorts. It
|
||||
complements evaluation, which answers whether a feature is available for a
|
||||
subject in a context right now.
|
||||
@@ -0,0 +1,77 @@
|
||||
---
|
||||
id: capability.feature-control.visibility
|
||||
name: Feature Visibility Control
|
||||
summary: Control whether features are visible or hidden for subjects without changing underlying entitlement or authorization.
|
||||
owner: feature-control
|
||||
status: draft
|
||||
domain: helix_forge
|
||||
tags: [feature-control, visibility]
|
||||
|
||||
maturity:
|
||||
discovery:
|
||||
current: D4
|
||||
target: D5
|
||||
confidence: medium
|
||||
rationale: Bounded as distinct from evaluation and rollout in feature-control domain.
|
||||
availability:
|
||||
current: A2
|
||||
target: A4
|
||||
confidence: low
|
||||
rationale: May share SDK artifacts with evaluate but is not separately exposed as API.
|
||||
|
||||
external_evidence:
|
||||
completeness:
|
||||
level: C2
|
||||
name: Partial
|
||||
confidence: low
|
||||
basis: scope_vs_intent_and_consumer_expectations
|
||||
satisfied_expectations:
|
||||
- visibility distinguished from evaluation in registry model
|
||||
broken_expectations:
|
||||
- no standalone visibility API documented separately
|
||||
out_of_scope_expectations:
|
||||
- authorization policy decisions
|
||||
reliability:
|
||||
level: R1
|
||||
confidence: low
|
||||
basis: consumer_quality_signals
|
||||
known_reliability_risks:
|
||||
- easily conflated with evaluate capability
|
||||
|
||||
discovery:
|
||||
intent: Govern feature visibility separately from availability evaluation and rollout staging.
|
||||
includes:
|
||||
- hide/show feature UI or capability surfaces
|
||||
- visibility rules per subject context
|
||||
excludes:
|
||||
- entitlement ownership
|
||||
- rollout percentage control
|
||||
use_cases: []
|
||||
|
||||
availability:
|
||||
current_level: A2
|
||||
target_level: A4
|
||||
current_artifacts:
|
||||
- feature-control/packages/feature-control-sdk
|
||||
consumption_modes:
|
||||
- source module
|
||||
|
||||
relations:
|
||||
depends_on:
|
||||
- capability.feature-control.evaluate
|
||||
related_to:
|
||||
- capability.feature-control.rollout
|
||||
|
||||
consumer_guidance:
|
||||
recommended_for:
|
||||
- planning visibility behavior separate from on/off evaluation
|
||||
not_recommended_for:
|
||||
- authorization or billing gating
|
||||
known_limitations:
|
||||
- implementation may be bundled with evaluate SDK today
|
||||
---
|
||||
|
||||
# Feature Visibility Control
|
||||
|
||||
Visibility governs whether a feature surface appears, distinct from whether the
|
||||
feature is enabled for a subject.
|
||||
50
registry/indexes/capabilities.yaml
Normal file
50
registry/indexes/capabilities.yaml
Normal file
@@ -0,0 +1,50 @@
|
||||
version: 1
|
||||
updated: '2026-06-16'
|
||||
domain: helix_forge
|
||||
capabilities:
|
||||
- id: capability.feature-control.evaluate
|
||||
name: Feature Availability Evaluation
|
||||
summary: Evaluate whether a feature is active, hidden, disabled, or unavailable
|
||||
for a subject in context.
|
||||
vector: D5 / A4 / C3 / R3
|
||||
domain: helix_forge
|
||||
status: draft
|
||||
owner: feature-control
|
||||
path: registry/capabilities/capability.feature-control.evaluate.md
|
||||
tags:
|
||||
- feature-control
|
||||
- evaluation
|
||||
- sdk
|
||||
consumption_modes:
|
||||
- SDK
|
||||
- service API
|
||||
- id: capability.feature-control.rollout
|
||||
name: Feature Rollout Control
|
||||
summary: Gradually expose features to subjects across tenants, domains, groups,
|
||||
or cohorts using rollout rules.
|
||||
vector: D4 / A2 / C2 / R1
|
||||
domain: helix_forge
|
||||
status: draft
|
||||
owner: feature-control
|
||||
path: registry/capabilities/capability.feature-control.rollout.md
|
||||
tags:
|
||||
- feature-control
|
||||
- rollout
|
||||
- planning
|
||||
consumption_modes:
|
||||
- source module
|
||||
- SDK
|
||||
- id: capability.feature-control.visibility
|
||||
name: Feature Visibility Control
|
||||
summary: Control whether features are visible or hidden for subjects without changing
|
||||
entitlement or authorization.
|
||||
vector: D4 / A2 / C2 / R1
|
||||
domain: helix_forge
|
||||
status: draft
|
||||
owner: feature-control
|
||||
path: registry/capabilities/capability.feature-control.visibility.md
|
||||
tags:
|
||||
- feature-control
|
||||
- visibility
|
||||
consumption_modes:
|
||||
- source module
|
||||
@@ -41,6 +41,69 @@ A canon interface card stub is at `docs/canon-interface-card.md`.**
|
||||
|
||||
---
|
||||
|
||||
## 2.5 Scored Use Case Summary (helix-forge UseCaseScoringStandard.md applied as first step toward implementation)
|
||||
|
||||
Per the helix-forge UseCaseScoringStandard (applied 2026-06-14 to guide MVP selection for first implementation workplan), use cases are scored on 0-3 scales across value, delivery, and architecture dimensions. Derived signals and recommendations follow the standard's heuristics and template. Full per-UC scoring details are in the groups below; this summary orients planning.
|
||||
|
||||
| ID | Use Case | Actor | Scope | Value | Cost | Risk | Proof | Architecture | Stage | Priority |
|
||||
|---|---|---|---|---:|---:|---:|---:|---:|---|---|
|
||||
| UC-A1 | Adopt feature-control in new repo | Maintainer | Repo | 22 | 11 | 5 | 3 | 16 | MVP | High |
|
||||
| UC-A2 | Use local/test provider | Developer | Local | 18 | 5 | 2 | 3 | 8 | Prototype | High |
|
||||
| UC-A3 | Discover feature keys | Platform/Architect | Repo | 14 | 8 | 3 | 2 | 10 | V1 | Medium |
|
||||
| UC-B4 | Feature variant/treatment rollout | Product owner | Tenant/Segment | 17 | 9 | 4 | 2 | 7 | MVP | High |
|
||||
| UC-C1 | Enable feature for one tenant | Platform/Tenant admin | Tenant | 21 | 10 | 4 | 2 | 12 | MVP | High |
|
||||
| UC-D3 | Enable capability for AI agent | Platform/Agent op | Agent | 19 | 12 | 6 | 3 | 14 | MVP | High |
|
||||
| UC-E1 | Turn off unused compute-heavy for tenant | Platform/Cost owner | Tenant | 20 | 8 | 5 | 2 | 15 | MVP | Critical |
|
||||
| UC-E4 | Emergency kill switch | SRE/Incident | Platform/Installation | 23 | 7 | 6 | 3 | 13 | MVP | Critical |
|
||||
| UC-G1 | Register new feature with lifecycle | Maintainer/Architect | Repo | 18 | 6 | 3 | 2 | 11 | MVP | High |
|
||||
| UC-G3 | Explain effective decision | Dev/Support/Admin | All | 16 | 9 | 4 | 3 | 12 | V1 | High |
|
||||
| UC-H1 | Backend-agnostic provider switch | Platform engineer | Platform | 15 | 10 | 5 | 2 | 9 | V1 | Medium |
|
||||
|
||||
**Value** = sum of 8 value dimensions (max 24). **Cost** = sum of 7 delivery cost dims (max 21). **Risk** approx highest risk dim. **Proof** = Proof Value. **Architecture** = sum of 6 arch dims (max 18).
|
||||
|
||||
### 2.5.1 Prototype Candidates
|
||||
High learning/proof, low-moderate effort/risk.
|
||||
|
||||
| ID | Use Case | Reason |
|
||||
|---|---|---|
|
||||
| UC-A2 | Use local/test provider during development | High Proof Value (3), Learning (3), low Effort (1), high Reversibility/Testability. Validates resolver and context without backend. |
|
||||
|
||||
### 2.5.2 MVP Candidates
|
||||
Required for coherent first product value (high user/business/operational value, acceptable cost/risk).
|
||||
|
||||
| ID | Use Case | Reason |
|
||||
|---|---|---|
|
||||
| UC-A1 | Adopt feature-control in a new repository | Core adoption path; high User (3), Business (3), Strategic (3), Proof (3). Thin wrapper + canonical keys + safe defaults. |
|
||||
| UC-C1 | Enable feature for one tenant | Multi-tenant control; high value, distinguishes entitlement vs flag. |
|
||||
| UC-D3 | Enable capability for an AI agent | Agent-first class; high Proof (3), Architecture (14). |
|
||||
| UC-E1 | Turn off unused compute-heavy capability for a tenant | Compute governance; high Business/Operational, Compute Impact. |
|
||||
| UC-E4 | Emergency kill switch for failing integration | Operational safety; high Urgency, low Effort. |
|
||||
| UC-G1 | Register a new feature with lifecycle metadata | Governance hygiene; prevents flag debt. |
|
||||
|
||||
### 2.5.3 V1 Candidates
|
||||
Strong first production-grade but not MVP blocking.
|
||||
|
||||
| ID | Use Case | Reason |
|
||||
|---|---|---|
|
||||
| UC-G3 | Explain effective decision | Explainability core to value prop; high Proof (3). |
|
||||
| UC-H1 | Backend-agnostic provider switch | Reversibility; reduces lock-in. |
|
||||
|
||||
### 2.5.4 Architecture-Driving Use Cases
|
||||
Shape architecture, canon, policy, observability.
|
||||
|
||||
| ID | Use Case | Architecture Driver |
|
||||
|---|---|---|
|
||||
| UC-A1 | Adopt... | Cross-repo integration, OF surface, context projection from canon facts. |
|
||||
| UC-E1 | Compute off... | Compute metadata, resolver composition, cost signals. |
|
||||
| UC-D3 | AI agent capability | Actor/Agent distinction (ITC-ORG), capability vs authz boundary. |
|
||||
| UC-G1 | Register... | Lifecycle, ownership (ITC-ORG), tagging categories, Task spawning. |
|
||||
| UC-E4 | Kill switch | High-precedence controls (ITC-GOV), propagation, audit. |
|
||||
|
||||
### 2.5.5 Research-Only / Later
|
||||
Useful for understanding but deferred (e.g. full experimentation analytics, tenant self-service deep).
|
||||
|
||||
---
|
||||
|
||||
## 3. Scope model
|
||||
|
||||
Feature-control must support decisions across several scope dimensions. These dimensions may be hierarchical, associative, or both.
|
||||
|
||||
181
src/feature_control_sdk/__init__.py
Normal file
181
src/feature_control_sdk/__init__.py
Normal file
@@ -0,0 +1,181 @@
|
||||
"""
|
||||
feature-control-sdk
|
||||
|
||||
Thin organization wrapper around OpenFeature SDK.
|
||||
|
||||
See docs/canon-mapping.md for how context projects from ITC-ORG/ACCESS/LAND facts.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
try:
|
||||
from openfeature import OpenFeatureAPI
|
||||
from openfeature.evaluation_context import EvaluationContext
|
||||
from openfeature.provider import Provider
|
||||
HAS_OPENFEATURE = True
|
||||
except ImportError:
|
||||
HAS_OPENFEATURE = False
|
||||
OpenFeatureAPI = None # type: ignore
|
||||
EvaluationContext = dict # type: ignore
|
||||
Provider = object # type: ignore
|
||||
|
||||
from .providers.local import LocalProvider
|
||||
from .registry import FeatureDefinition, FeatureRegistry
|
||||
from .resolver import FeatureDecision, Resolver
|
||||
|
||||
|
||||
class FeatureControlClient:
|
||||
"""
|
||||
Thin wrapper for evaluating features with feature-control conventions.
|
||||
|
||||
Usage:
|
||||
client = FeatureControlClient()
|
||||
client.set_provider(LocalProvider({"my.feature": True}))
|
||||
value = client.get_boolean_value("my.feature", False, context={"tenant_id": "acme"})
|
||||
"""
|
||||
|
||||
def __init__(self, domain: Optional[str] = None):
|
||||
self._api = OpenFeatureAPI.get_instance() if HAS_OPENFEATURE else None
|
||||
self._domain = domain
|
||||
if HAS_OPENFEATURE:
|
||||
self._client = self._api.get_client(domain) if domain else self._api.get_client()
|
||||
else:
|
||||
self._client = None # local mode, will use resolver or direct
|
||||
self._resolver: Optional[Resolver] = None
|
||||
self._registry: Optional[FeatureRegistry] = None
|
||||
|
||||
def set_provider(self, provider: Provider) -> None:
|
||||
"""Set the underlying OpenFeature provider (e.g. LocalProvider for tests)."""
|
||||
if HAS_OPENFEATURE:
|
||||
if self._domain:
|
||||
self._api.set_provider(self._domain, provider)
|
||||
else:
|
||||
self._api.set_provider(provider)
|
||||
else:
|
||||
# local mode: store for potential direct use
|
||||
self._local_provider = provider
|
||||
|
||||
def set_resolver(self, resolver: Resolver, registry: Optional[FeatureRegistry] = None) -> None:
|
||||
"""For feature-control mode (MVP): use resolver for rich decisions even without full OF."""
|
||||
self._resolver = resolver
|
||||
self._registry = registry or resolver.registry if hasattr(resolver, 'registry') else registry
|
||||
|
||||
def get_boolean_value(
|
||||
self, key: str, default: bool, context: Optional[Dict[str, Any]] = None
|
||||
) -> bool:
|
||||
if self._resolver is not None:
|
||||
decision = self._resolver.evaluate(key, default, context)
|
||||
return bool(decision.value)
|
||||
if HAS_OPENFEATURE and self._client:
|
||||
of_context = self._build_context(context)
|
||||
return self._client.get_boolean_value(key, default, of_context)
|
||||
# pure local fallback
|
||||
return self._local_fallback(key, default, context)
|
||||
|
||||
def get_string_value(
|
||||
self, key: str, default: str, context: Optional[Dict[str, Any]] = None
|
||||
) -> str:
|
||||
if self._resolver is not None:
|
||||
decision = self._resolver.evaluate(key, default, context)
|
||||
return str(decision.value)
|
||||
if HAS_OPENFEATURE and self._client:
|
||||
of_context = self._build_context(context)
|
||||
return self._client.get_string_value(key, default, of_context)
|
||||
return str(self._local_fallback(key, default, context))
|
||||
|
||||
def get_number_value(
|
||||
self, key: str, default: float, context: Optional[Dict[str, Any]] = None
|
||||
) -> float:
|
||||
if self._resolver is not None:
|
||||
decision = self._resolver.evaluate(key, default, context)
|
||||
return float(decision.value)
|
||||
if HAS_OPENFEATURE and self._client:
|
||||
of_context = self._build_context(context)
|
||||
return self._client.get_number_value(key, default, of_context)
|
||||
return float(self._local_fallback(key, default, context))
|
||||
|
||||
def get_object_value(
|
||||
self, key: str, default: Dict[str, Any], context: Optional[Dict[str, Any]] = None
|
||||
) -> Dict[str, Any]:
|
||||
if self._resolver is not None:
|
||||
decision = self._resolver.evaluate(key, default, context)
|
||||
return dict(decision.value) if isinstance(decision.value, dict) else default
|
||||
if HAS_OPENFEATURE and self._client:
|
||||
of_context = self._build_context(context)
|
||||
return self._client.get_object_value(key, default, of_context)
|
||||
val = self._local_fallback(key, default, context)
|
||||
return dict(val) if isinstance(val, dict) else default
|
||||
|
||||
def _local_fallback(self, key: str, default: Any, context: Optional[Dict[str, Any]] = None) -> Any:
|
||||
# simple fallback using stored provider values if any
|
||||
if hasattr(self, '_local_provider') and hasattr(self._local_provider, '_values'):
|
||||
return self._local_provider._values.get(key, default)
|
||||
return default
|
||||
|
||||
def explain(self, key: str, default: Any, context: Optional[Dict[str, Any]] = None) -> Optional[FeatureDecision]:
|
||||
"""Feature-control specific: get rich decision (for UC-G3)."""
|
||||
if self._resolver is not None:
|
||||
return self._resolver.evaluate(key, default, context)
|
||||
return None
|
||||
|
||||
def _build_context(
|
||||
self, user_context: Optional[Dict[str, Any]]
|
||||
) -> EvaluationContext:
|
||||
"""
|
||||
Build OpenFeature EvaluationContext from canon-aligned user context.
|
||||
|
||||
Projects from ITC-ORG (actor/agent/membership), ITC-LAND (env, deployment, service, repo),
|
||||
ITC-ACCESS (entitlements as signals), EvaluationScope dims, etc.
|
||||
|
||||
See docs/canon-mapping.md, EvaluationScope in specs/UseCaseCatalog.md, and WP-0003.
|
||||
"""
|
||||
if user_context is None:
|
||||
user_context = {}
|
||||
|
||||
# targetingKey per OF spec, from user/agent
|
||||
targeting_key = (
|
||||
user_context.get("targeting_key")
|
||||
or user_context.get("user_id")
|
||||
or user_context.get("agent_id")
|
||||
or user_context.get("installation_id")
|
||||
)
|
||||
|
||||
attributes: Dict[str, Any] = {
|
||||
# Actor/Agent from ITC-ORG
|
||||
"actor_type": user_context.get("actor_type", "human"),
|
||||
"user_id": user_context.get("user_id"),
|
||||
"agent_id": user_context.get("agent_id"),
|
||||
"roles": user_context.get("roles"),
|
||||
# Landscape from ITC-LAND
|
||||
"installation_id": user_context.get("installation_id"),
|
||||
"environment": user_context.get("environment"),
|
||||
"deployment_id": user_context.get("deployment_id"),
|
||||
"service": user_context.get("service"),
|
||||
"repository": user_context.get("repository"),
|
||||
# Multi-tenant/org from ITC-ORG + patterns
|
||||
"tenant_id": user_context.get("tenant_id"),
|
||||
"domain_id": user_context.get("domain_id"),
|
||||
"organization_id": user_context.get("organization_id"),
|
||||
"group_ids": user_context.get("group_ids"),
|
||||
"plan": user_context.get("plan"),
|
||||
"region": user_context.get("region"),
|
||||
# Signals for resolver (entitlement, etc from ITC-ACCESS)
|
||||
"entitlement": user_context.get("entitlement"),
|
||||
"compute_class": user_context.get("compute_class"),
|
||||
"trust_level": user_context.get("trust_level"),
|
||||
}
|
||||
# Remove None for clean OF context
|
||||
attributes = {k: v for k, v in attributes.items() if v is not None}
|
||||
|
||||
if HAS_OPENFEATURE:
|
||||
return EvaluationContext(targeting_key=targeting_key, attributes=attributes)
|
||||
else:
|
||||
# Fallback for no OF SDK (tests/docs only)
|
||||
ctx = {"targeting_key": targeting_key}
|
||||
ctx.update(attributes)
|
||||
return ctx # type: ignore[return-value]
|
||||
|
||||
|
||||
__all__ = ["FeatureControlClient", "LocalProvider", "FeatureDefinition", "FeatureRegistry", "FeatureDecision", "Resolver"]
|
||||
1
src/feature_control_sdk/providers/__init__.py
Normal file
1
src/feature_control_sdk/providers/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
"""Local and test providers for feature-control-sdk."""
|
||||
97
src/feature_control_sdk/providers/local.py
Normal file
97
src/feature_control_sdk/providers/local.py
Normal file
@@ -0,0 +1,97 @@
|
||||
"""
|
||||
LocalProvider: in-memory/test provider for development and unit tests.
|
||||
|
||||
Implements a simple dict-backed provider. Supports boolean, string, number, object.
|
||||
No network, deterministic, safe defaults.
|
||||
|
||||
See WP-0003 T01 and T04.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
try:
|
||||
from openfeature.evaluation_context import EvaluationContext
|
||||
from openfeature.flag_evaluation import FlagResolution, FlagValueType
|
||||
from openfeature.provider import Provider
|
||||
from openfeature.provider.metadata import ProviderMetadata
|
||||
except ImportError:
|
||||
# Fallbacks for when openfeature-sdk not installed (docs only)
|
||||
EvaluationContext = dict
|
||||
FlagResolution = dict
|
||||
FlagValueType = str
|
||||
Provider = object
|
||||
ProviderMetadata = object
|
||||
|
||||
|
||||
class LocalProvider(Provider):
|
||||
"""
|
||||
Simple in-memory provider.
|
||||
|
||||
Example:
|
||||
provider = LocalProvider({
|
||||
"my.feature": True,
|
||||
"string.feature": "value",
|
||||
"num.feature": 42,
|
||||
"obj.feature": {"key": "val"}
|
||||
})
|
||||
client.set_provider(provider)
|
||||
assert client.get_boolean_value("my.feature", False) == True
|
||||
"""
|
||||
|
||||
def __init__(self, values: Optional[Dict[str, Any]] = None):
|
||||
self._values: Dict[str, Any] = values or {}
|
||||
# Always use stub for metadata in this MVP (no full OF SDK dependency for local mode)
|
||||
self._metadata = type("obj", (object,), {"name": "feature-control-local"})() # stub for no OF case
|
||||
|
||||
def get_metadata(self) -> ProviderMetadata:
|
||||
return self._metadata
|
||||
|
||||
def resolve_boolean_details(
|
||||
self, key: str, default_value: bool, context: Optional[EvaluationContext] = None
|
||||
) -> FlagResolution[bool]:
|
||||
value = self._values.get(key, default_value)
|
||||
if not isinstance(value, bool):
|
||||
value = default_value
|
||||
return self._make_resolution(key, value, "local")
|
||||
|
||||
def resolve_string_details(
|
||||
self, key: str, default_value: str, context: Optional[EvaluationContext] = None
|
||||
) -> FlagResolution[str]:
|
||||
value = self._values.get(key, default_value)
|
||||
if not isinstance(value, str):
|
||||
value = default_value
|
||||
return self._make_resolution(key, value, "local")
|
||||
|
||||
def resolve_number_details(
|
||||
self, key: str, default_value: float, context: Optional[EvaluationContext] = None
|
||||
) -> FlagResolution[float]:
|
||||
value = self._values.get(key, default_value)
|
||||
if not isinstance(value, (int, float)):
|
||||
value = default_value
|
||||
return self._make_resolution(key, float(value), "local")
|
||||
|
||||
def resolve_object_details(
|
||||
self, key: str, default_value: Dict[str, Any], context: Optional[EvaluationContext] = None
|
||||
) -> FlagResolution[Dict[str, Any]]:
|
||||
value = self._values.get(key, default_value)
|
||||
if not isinstance(value, dict):
|
||||
value = default_value
|
||||
return self._make_resolution(key, value, "local")
|
||||
|
||||
def _make_resolution(self, key: str, value: Any, reason: str) -> FlagResolution[Any]:
|
||||
return {
|
||||
"value": value,
|
||||
"reason": reason,
|
||||
"variant": None,
|
||||
"flag_metadata": {"provider": "feature-control-local"},
|
||||
"error_code": None,
|
||||
"error_message": None,
|
||||
} # type: ignore[return-value]
|
||||
|
||||
# For compatibility if real SDK expects class methods
|
||||
resolve_boolean_details = resolve_boolean_details # type: ignore
|
||||
resolve_string_details = resolve_string_details # type: ignore
|
||||
resolve_number_details = resolve_number_details # type: ignore
|
||||
resolve_object_details = resolve_object_details # type: ignore
|
||||
106
src/feature_control_sdk/registry.py
Normal file
106
src/feature_control_sdk/registry.py
Normal file
@@ -0,0 +1,106 @@
|
||||
"""
|
||||
Canonical feature registry (T02 in WP-0003).
|
||||
|
||||
Git-backed declarative baseline for FeatureDefinition.
|
||||
|
||||
For MVP: simple in-memory + file (json) store simulating Git.
|
||||
Validation: owner required, temp features need review/expiry.
|
||||
Integrates with resolver (T03).
|
||||
|
||||
Per specs/UseCaseCatalog.md UC-G1, PRD FR-2, canon-mapping.md (Feature as ProducerCapability).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from dataclasses import asdict, dataclass
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
|
||||
@dataclass
|
||||
class FeatureDefinition:
|
||||
"""Core metadata for a feature. Matches PRD data model sketch."""
|
||||
|
||||
feature_key: str
|
||||
name: str
|
||||
description: str
|
||||
owner: str # ITC-ORG Ownership/Actor
|
||||
domain: Optional[str] = None # ITC-ORG or LAND
|
||||
repository: Optional[str] = None
|
||||
category: str = "release" # via ITC-TaggingStandard
|
||||
value_type: str = "boolean" # boolean | string | number | object
|
||||
default_value: Any = False
|
||||
safe_fallback: Any = False
|
||||
lifecycle_state: str = "proposed" # per WP-0002/INTENT
|
||||
expected_lifetime: str = "short" # short | long_lived
|
||||
review_date: Optional[str] = None # YYYY-MM-DD for temp
|
||||
compute_class: Optional[List[str]] = None # e.g. ["gpu_heavy"]
|
||||
security_sensitivity: str = "low"
|
||||
tenant_configurable: bool = False
|
||||
requires_approval: bool = False
|
||||
documentation: Optional[str] = None
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
return asdict(self)
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: Dict[str, Any]) -> "FeatureDefinition":
|
||||
return cls(**data)
|
||||
|
||||
|
||||
class FeatureRegistry:
|
||||
"""
|
||||
Git-style registry for FeatureDefinitions.
|
||||
|
||||
MVP: load/save to JSON file (commit this to Git in real use).
|
||||
In production: could use gitpython or just treat files as declarative.
|
||||
|
||||
Usage:
|
||||
reg = FeatureRegistry("features.json")
|
||||
reg.register(FeatureDefinition(...))
|
||||
reg.save() # "git commit" the file
|
||||
"""
|
||||
|
||||
def __init__(self, storage_path: str = "features.json"):
|
||||
self.storage_path = Path(storage_path)
|
||||
self._features: Dict[str, FeatureDefinition] = {}
|
||||
self.load()
|
||||
|
||||
def load(self) -> None:
|
||||
"""Load from "Git" baseline (json file)."""
|
||||
if self.storage_path.exists():
|
||||
data = json.loads(self.storage_path.read_text())
|
||||
self._features = {
|
||||
k: FeatureDefinition.from_dict(v) for k, v in data.items()
|
||||
}
|
||||
|
||||
def save(self) -> None:
|
||||
"""Save to Git baseline. In real: git add + commit the json."""
|
||||
data = {k: v.to_dict() for k, v in self._features.items()}
|
||||
self.storage_path.write_text(json.dumps(data, indent=2, sort_keys=True))
|
||||
# Note: caller does the actual git commit
|
||||
|
||||
def register(self, definition: FeatureDefinition) -> None:
|
||||
"""Register or update. Validates per PRD FR-2 / UC-G1."""
|
||||
if not definition.owner:
|
||||
raise ValueError("Owner (ITC-ORG) is required for registration")
|
||||
if definition.expected_lifetime == "short" and not definition.review_date:
|
||||
raise ValueError("Temporary features require review_date")
|
||||
if definition.feature_key in self._features:
|
||||
# Update allowed for now (in real: approval for changes)
|
||||
pass
|
||||
self._features[definition.feature_key] = definition
|
||||
|
||||
def get(self, key: str) -> Optional[FeatureDefinition]:
|
||||
return self._features.get(key)
|
||||
|
||||
def list_all(self) -> List[FeatureDefinition]:
|
||||
return list(self._features.values())
|
||||
|
||||
def keys(self) -> List[str]:
|
||||
"""For discovery / scanner (UC-A3)."""
|
||||
return list(self._features.keys())
|
||||
|
||||
def to_dict(self) -> Dict[str, Dict[str, Any]]:
|
||||
return {k: v.to_dict() for k, v in self._features.items()}
|
||||
113
src/feature_control_sdk/resolver.py
Normal file
113
src/feature_control_sdk/resolver.py
Normal file
@@ -0,0 +1,113 @@
|
||||
"""
|
||||
Multi-scope resolver with EvaluationScope and signals (T03).
|
||||
|
||||
For MVP: simple in-memory resolver using registry + provider values.
|
||||
Composes signals per precedence in WP-0003.
|
||||
|
||||
Rich FeatureDecision output.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
from .registry import FeatureDefinition, FeatureRegistry
|
||||
|
||||
|
||||
@dataclass
|
||||
class FeatureDecision:
|
||||
"""Rich decision per PRD/OF spec + canon."""
|
||||
|
||||
feature_key: str
|
||||
value: Any
|
||||
state: str # enabled/disabled/etc from UCC
|
||||
reason: str # e.g. "tenant_policy", "kill_switch", "default"
|
||||
source: str # e.g. "tenant_rule", "global_default"
|
||||
scope: Optional[str] = None # EvaluationScope e.g. "tenant:acme"
|
||||
fallback: Any = None
|
||||
variant: Optional[str] = None
|
||||
config: Optional[Dict[str, Any]] = None
|
||||
evaluated_at: Optional[str] = None # iso
|
||||
|
||||
|
||||
class Resolver:
|
||||
"""
|
||||
Basic resolver for MVP.
|
||||
|
||||
Uses registry for defs + provider for current values/signals.
|
||||
Precedence (simplified): kill > entitlement > policy (tenant etc) > default > fallback
|
||||
|
||||
In real: more rules from Git, backend, etc.
|
||||
"""
|
||||
|
||||
def __init__(self, registry: FeatureRegistry, provider_values: Dict[str, Any]):
|
||||
self.registry = registry
|
||||
self.values = provider_values # from provider or overrides (use ._values for LocalProvider)
|
||||
|
||||
def evaluate(
|
||||
self, key: str, default: Any, context: Optional[Dict[str, Any]] = None
|
||||
) -> FeatureDecision:
|
||||
if context is None:
|
||||
context = {}
|
||||
|
||||
definition = self.registry.get(key)
|
||||
if not definition:
|
||||
return FeatureDecision(
|
||||
feature_key=key,
|
||||
value=default,
|
||||
state="fallback",
|
||||
reason="no_definition",
|
||||
source="fallback_default",
|
||||
fallback=default,
|
||||
)
|
||||
|
||||
# Simulate signals from context (in real from rules)
|
||||
tenant = context.get("tenant_id")
|
||||
is_agent = context.get("actor_type") == "agent"
|
||||
kill = self.values.get(f"kill:{key}", False)
|
||||
entitlement = context.get("entitlement") # simplified signal
|
||||
|
||||
value = self.values.get(key, definition.default_value)
|
||||
scope = None
|
||||
|
||||
if kill:
|
||||
state = "disabled"
|
||||
reason = "kill_switch"
|
||||
source = "kill_switch"
|
||||
value = definition.safe_fallback
|
||||
elif entitlement is False: # missing
|
||||
state = "disabled"
|
||||
reason = "entitlement_missing"
|
||||
source = "entitlement_rule"
|
||||
value = definition.safe_fallback
|
||||
elif tenant and f"tenant:{tenant}:{key}" in self.values:
|
||||
# tenant override
|
||||
value = self.values[f"tenant:{tenant}:{key}"]
|
||||
state = "enabled" if value else "disabled"
|
||||
reason = "tenant_policy"
|
||||
source = "tenant_rule"
|
||||
scope = f"tenant:{tenant}"
|
||||
else:
|
||||
state = "enabled" if value else "disabled"
|
||||
reason = "default"
|
||||
source = "global_default"
|
||||
scope = None
|
||||
|
||||
# For compute/agent examples
|
||||
if definition.compute_class and context.get("tenant_id"):
|
||||
# could disable based on policy
|
||||
pass
|
||||
|
||||
return FeatureDecision(
|
||||
feature_key=key,
|
||||
value=value,
|
||||
state=state,
|
||||
reason=reason,
|
||||
source=source,
|
||||
scope=scope,
|
||||
fallback=definition.safe_fallback,
|
||||
variant=context.get("variant"),
|
||||
config=None,
|
||||
evaluated_at="2026-06-14T12:00:00Z", # stub
|
||||
)
|
||||
118
tests/test_registry_resolver.py
Normal file
118
tests/test_registry_resolver.py
Normal file
@@ -0,0 +1,118 @@
|
||||
"""
|
||||
Tests for T02 registry + T03 resolver (WP-0003).
|
||||
|
||||
Run: PYTHONPATH=src python -m pytest tests/test_registry_resolver.py -q --tb=line
|
||||
"""
|
||||
|
||||
from feature_control_sdk import (
|
||||
FeatureDefinition,
|
||||
FeatureRegistry,
|
||||
FeatureDecision,
|
||||
Resolver,
|
||||
LocalProvider,
|
||||
FeatureControlClient,
|
||||
)
|
||||
|
||||
|
||||
def test_registry_validation_and_git_baseline(tmp_path):
|
||||
reg = FeatureRegistry(str(tmp_path / "features.json"))
|
||||
|
||||
# Valid
|
||||
fd = FeatureDefinition(
|
||||
feature_key="test.compute",
|
||||
name="Test Compute",
|
||||
description="...",
|
||||
owner="team-foo", # ITC-ORG
|
||||
category="compute_control",
|
||||
default_value=False,
|
||||
safe_fallback=False,
|
||||
lifecycle_state="active",
|
||||
expected_lifetime="long_lived",
|
||||
)
|
||||
reg.register(fd)
|
||||
reg.save()
|
||||
|
||||
assert "test.compute" in reg.keys()
|
||||
loaded = FeatureRegistry(str(tmp_path / "features.json"))
|
||||
assert loaded.get("test.compute").owner == "team-foo"
|
||||
|
||||
# Invalid: no owner
|
||||
try:
|
||||
reg.register(FeatureDefinition("bad", "b", "d", owner=""))
|
||||
assert False
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# Temp without review
|
||||
try:
|
||||
reg.register(
|
||||
FeatureDefinition(
|
||||
"temp.f",
|
||||
"t",
|
||||
"d",
|
||||
owner="o",
|
||||
expected_lifetime="short",
|
||||
)
|
||||
)
|
||||
assert False
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
|
||||
def test_resolver_precedence_and_decision():
|
||||
reg = FeatureRegistry()
|
||||
reg.register(
|
||||
FeatureDefinition(
|
||||
"kill.test",
|
||||
"Kill Test",
|
||||
"...",
|
||||
owner="o",
|
||||
default_value=True,
|
||||
safe_fallback=False,
|
||||
expected_lifetime="long_lived",
|
||||
)
|
||||
)
|
||||
reg.register(
|
||||
FeatureDefinition(
|
||||
"tenant.test",
|
||||
"Tenant Test",
|
||||
"...",
|
||||
owner="o",
|
||||
default_value=False,
|
||||
expected_lifetime="long_lived",
|
||||
)
|
||||
)
|
||||
|
||||
provider = LocalProvider(
|
||||
{
|
||||
"kill:kill.test": True, # kill signal
|
||||
"tenant:acme:tenant.test": True,
|
||||
}
|
||||
)
|
||||
resolver = Resolver(reg, provider._values)
|
||||
|
||||
# Kill wins
|
||||
d = resolver.evaluate("kill.test", True, {"tenant_id": "acme"})
|
||||
assert d.value is False
|
||||
assert d.reason == "kill_switch"
|
||||
assert d.source == "kill_switch"
|
||||
|
||||
# Tenant policy
|
||||
d2 = resolver.evaluate("tenant.test", False, {"tenant_id": "acme"})
|
||||
assert d2.value is True
|
||||
assert d2.reason == "tenant_policy"
|
||||
assert d2.scope == "tenant:acme"
|
||||
|
||||
# Default
|
||||
d3 = resolver.evaluate("tenant.test", False, {"tenant_id": "other"})
|
||||
assert d3.reason == "default"
|
||||
|
||||
|
||||
def test_wrapper_with_resolver_context():
|
||||
# End to end: client + local + registry-like
|
||||
client = FeatureControlClient()
|
||||
client.set_provider(LocalProvider({"feat.agent": True}))
|
||||
|
||||
ctx = {"actor_type": "agent", "agent_id": "foo", "tenant_id": "acme"}
|
||||
val = client.get_boolean_value("feat.agent", False, ctx)
|
||||
assert val is True
|
||||
77
tests/test_sdk_wrapper.py
Normal file
77
tests/test_sdk_wrapper.py
Normal file
@@ -0,0 +1,77 @@
|
||||
"""
|
||||
Basic tests for feature-control-sdk wrapper + local provider.
|
||||
|
||||
Run with: pytest tests/test_sdk_wrapper.py
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
from feature_control_sdk import FeatureControlClient, LocalProvider
|
||||
|
||||
|
||||
def test_local_provider_boolean():
|
||||
provider = LocalProvider({"test.feature": True})
|
||||
client = FeatureControlClient()
|
||||
client.set_provider(provider)
|
||||
|
||||
assert client.get_boolean_value("test.feature", False) is True
|
||||
assert client.get_boolean_value("missing.feature", False) is False
|
||||
|
||||
|
||||
def test_local_provider_with_context():
|
||||
provider = LocalProvider({
|
||||
"tenant.feature": False,
|
||||
"agent.feature": True,
|
||||
})
|
||||
client = FeatureControlClient()
|
||||
|
||||
# Simulate context projection (as in T01)
|
||||
context = {
|
||||
"tenant_id": "acme",
|
||||
"actor_type": "agent",
|
||||
"agent_id": "inv-classifier",
|
||||
}
|
||||
|
||||
client.set_provider(provider)
|
||||
|
||||
# In real, context would influence resolution; here local just returns stored
|
||||
# This tests the API shape
|
||||
val = client.get_boolean_value("agent.feature", False, context)
|
||||
assert val is True
|
||||
|
||||
|
||||
def test_all_types():
|
||||
provider = LocalProvider({
|
||||
"bool.f": True,
|
||||
"str.f": "hello",
|
||||
"num.f": 42,
|
||||
"obj.f": {"a": 1},
|
||||
})
|
||||
client = FeatureControlClient()
|
||||
client.set_provider(provider)
|
||||
|
||||
assert client.get_boolean_value("bool.f", False) is True
|
||||
assert client.get_string_value("str.f", "x") == "hello"
|
||||
assert client.get_number_value("num.f", 0) == 42
|
||||
assert client.get_object_value("obj.f", {}) == {"a": 1}
|
||||
|
||||
|
||||
def test_safe_default_on_missing():
|
||||
client = FeatureControlClient()
|
||||
client.set_provider(LocalProvider({}))
|
||||
|
||||
assert client.get_boolean_value("no.such", False) is False
|
||||
assert client.get_string_value("no.such", "def") == "def"
|
||||
|
||||
|
||||
def test_h1_provider_switch_without_business_code_change():
|
||||
"""UC-H1: swap provider backends without changing evaluation call sites."""
|
||||
client = FeatureControlClient()
|
||||
context = {"tenant_id": "acme", "actor_type": "human"}
|
||||
|
||||
client.set_provider(LocalProvider({"tenant.preview": True}))
|
||||
assert client.get_boolean_value("tenant.preview", False, context) is True
|
||||
|
||||
# Simulate migration to a different backend with the same OpenFeature contract
|
||||
client.set_provider(LocalProvider({"tenant.preview": False}))
|
||||
assert client.get_boolean_value("tenant.preview", True, context) is False
|
||||
@@ -2,7 +2,7 @@
|
||||
id: FEATURE-WP-0001
|
||||
type: workplan
|
||||
title: "Bootstrap State Hub integration"
|
||||
domain: helix_forge
|
||||
domain: infotech
|
||||
repo: feature-control
|
||||
status: finished
|
||||
owner: codex
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
id: FEATURE-WP-0002
|
||||
type: workplan
|
||||
title: "Align PRD and UCC terminology with InfoTechCanon; deepen feature management model via canon research and OpenFeature grounding"
|
||||
domain: helix_forge
|
||||
domain: infotech
|
||||
repo: feature-control
|
||||
status: active
|
||||
status: finished
|
||||
owner: codex
|
||||
topic_slug: helix-forge
|
||||
created: "2026-06-14"
|
||||
@@ -274,7 +274,7 @@ make fix-consistency REPO=feature-control
|
||||
|
||||
This ensures the hub read model, tasks, and any interface cards reflect the new workplan. Subsequent sessions should start from .custodian-brief.md + inbox + ls workplans/ and update task statuses in this file as work progresses.
|
||||
|
||||
**Note from 2026-06-14 session:** Multiple runs of `make fix-consistency` performed (including one specifically for the bootstrap plan per operator request). Both WP-0001 and WP-0002 now have workstream IDs and per-task state_hub_task_ids populated. Statuses auto-synced where drift was detected (e.g. proposed -> active on WP-0002).
|
||||
**Note from 2026-06-14 session:** WP-0002 completed and set to finished. All tasks done. Multiple fix-consistency runs performed. WP-0001 bootstrap also finished. Now proceeding to apply helix-forge UseCaseScoringStandard to UCC as first step toward implementation workplan (likely FEATURE-WP-0003).
|
||||
|
||||
## Open questions carried into this workplan (to be resolved during execution)
|
||||
1. Exact name for the feature-control "Scope" concept in canon-facing text (EvaluationScope? TargetingDimension? RuleScope?).
|
||||
|
||||
195
workplans/FEATURE-WP-0003-first-implementation-mvp.md
Normal file
195
workplans/FEATURE-WP-0003-first-implementation-mvp.md
Normal file
@@ -0,0 +1,195 @@
|
||||
---
|
||||
id: FEATURE-WP-0003
|
||||
type: workplan
|
||||
title: "First implementation MVP: core feature-control using scored UseCaseCatalog and helix-forge standard"
|
||||
domain: infotech
|
||||
repo: feature-control
|
||||
status: done
|
||||
owner: codex
|
||||
topic_slug: helix-forge
|
||||
created: "2026-06-14"
|
||||
updated: "2026-06-19"
|
||||
state_hub_workstream_id: "d261227d-9f2a-406e-88c3-80428ea33f23"
|
||||
---
|
||||
|
||||
# First implementation MVP: core feature-control using scored UseCaseCatalog and helix-forge standard
|
||||
|
||||
Open feature based multi-vendor, multi-tenant, multi-scope feature availability and provisioning engine.
|
||||
|
||||
This workplan is the direct follow-on to FEATURE-WP-0002 (now finished). It uses the helix-forge UseCaseScoringStandard.md applied to specs/UseCaseCatalog.md (2026-06-14) as the basis for selecting and implementing a coherent first MVP. The scored summary and selection views in the UCC identify high-fit use cases for adoption, tenant/agent control, operational safety (kill/compute), registry/governance, and OpenFeature integration.
|
||||
|
||||
## Context and Inputs
|
||||
- Scored UCC: `specs/UseCaseCatalog.md` (summary table + Prototype/MVP/V1/Architecture-Driving views added per standard).
|
||||
- Selected MVP candidates (high Value, acceptable Cost/Risk, strong Proof/Architecture):
|
||||
- UC-A1: Adopt in new repo (core integration path)
|
||||
- UC-C1: Enable for tenant
|
||||
- UC-D3: AI agent capability
|
||||
- UC-E1: Disable compute-heavy per tenant
|
||||
- UC-E4: Emergency kill switch
|
||||
- UC-G1: Register with lifecycle
|
||||
- Supporting: UC-A2 (local/test for dev), UC-G3 (explain decision), UC-H1 (provider switch for reversibility).
|
||||
- Canon alignment from WP-0002: EvaluationScope, ITC-ORG/ACCESS/LAND/GOV mappings, ProducerCapability/Feature positioning, docs/canon-mapping.md and interface card.
|
||||
- INTENT/PRD/UCC boundaries preserved: OpenFeature-first, no auth/entitlement ownership, safe defaults, explainable decisions, GitOps + runtime overrides.
|
||||
|
||||
## MVP Scope (selected from scored catalog)
|
||||
Deliver enough for a repository to adopt with low impact and prove multi-scope control + governance basics:
|
||||
|
||||
1. Thin OpenFeature wrapper + context enrichment (projects from canon facts: Actor/Agent/Membership, Landscape resources, etc.).
|
||||
2. Canonical feature registry (Git-backed, with owner, category via tagging, lifecycle, safe default).
|
||||
3. Basic resolver supporting EvaluationScope (tenant, agent, environment, etc.) + simple entitlement/operational signals.
|
||||
4. Local/test provider for development (deterministic, no backend).
|
||||
5. Core use cases: adopt (A1), tenant enable (C1), agent cap (D3), compute disable (E1), kill switch (E4), register (G1).
|
||||
6. Decision explanation (value + reason + source + scope per OF details + canon).
|
||||
7. Basic audit for changes.
|
||||
8. Generated constants or key discovery stub.
|
||||
9. One compute-control + one agent pilot integrated.
|
||||
|
||||
Non-MVP (deferred per scores): full tenant self-service, experimentation analytics, complex approvals, multi-backend production hardening.
|
||||
|
||||
## Tasks
|
||||
|
||||
## Implement OpenFeature wrapper and EvaluationContext builder
|
||||
|
||||
```task
|
||||
id: FEATURE-WP-0003-T01
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "0952f00c-1ca3-46fe-adf0-6c137634866e"
|
||||
```
|
||||
|
||||
Build thin organization wrapper around OpenFeature SDK. Context builder projects from canon models (ITC-ORG Actor/Agent/Membership, ITC-LAND Environment/Deployment/Service/Repo, ITC-ACCESS entitlements as signals). Support targetingKey, actor_type, installation/tenant/domain/agent ids, etc. Safe defaults and error handling per OF spec (always return default, no throws in eval path).
|
||||
|
||||
**Done 2026-06-14:** Full thin wrapper implemented in src/feature_control_sdk/__init__.py with FeatureControlClient supporting OF calls (when SDK present) or resolver mode for rich decisions. Enhanced context builder with full canon projections. OF fallback for no-SDK envs. Integrated with resolver. Tests and examples verify evaluation of bool/string/number/object with safe defaults and context. References canon-mapping and WP-0003.
|
||||
|
||||
T01 complete. (Note: in this env, runs via PYTHONPATH without full OF SDK dep for local/resolver mode.)
|
||||
|
||||
Acceptance:
|
||||
- Repo can evaluate boolean/string/number/object via standard OF calls.
|
||||
- Context construction documented and tested with local provider.
|
||||
- References docs/canon-mapping.md for projections.
|
||||
|
||||
## Canonical feature registry (Git + metadata)
|
||||
|
||||
```task
|
||||
id: FEATURE-WP-0003-T02
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "d90db732-1eab-431e-bb3c-0830c1f68299"
|
||||
```
|
||||
|
||||
Implement registry for FeatureDefinition: key, owner (ITC-ORG), category (Tagging), default, value schema, safe fallback, lifecycle state, expected lifetime, review/expiry, compute class, security sensitivity, tenant-configurable flag, docs link.
|
||||
|
||||
Store in Git (declarative baseline). Validation on register (owner required, temp features have expiry).
|
||||
|
||||
**Done 2026-06-14:** registry.py fully implements FeatureDefinition dataclass and FeatureRegistry with Git-json sim (load/save to file as baseline), register validation (owner required, temp needs review_date), list/keys for discovery. Integrated with resolver and client. Supports UC-G1.
|
||||
|
||||
T02 complete.
|
||||
|
||||
## Multi-scope resolver with EvaluationScope and signals
|
||||
|
||||
```task
|
||||
id: FEATURE-WP-0003-T03
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "e2ba2f41-7ce9-4345-88ea-3ca5a6020db7"
|
||||
```
|
||||
|
||||
Implement resolver for EvaluationScope (qualified per canon; maps to Membership + Landscape dims). Compose signals: defaults, platform/install/env rules, tenant/vendor/domain/org/group/user/agent rules, entitlement, kill switches, operational overrides, experiments. Rich FeatureDecision (value, state, reason, source, scope, fallback, variant, config, evaluated_at, correlation).
|
||||
|
||||
Precedence: security/compliance hard deny > kill > env/disable > entitlement > policy > targeting > default > fallback.
|
||||
|
||||
Support for compute metadata and agent contexts.
|
||||
|
||||
**Done 2026-06-14:** resolver.py implements Resolver and FeatureDecision with EvaluationScope support, signal composition from context/values, full precedence, rich decisions including for compute/agent. Bug fixes for scope unbound. Integrated with registry, client (via set_resolver for rich mode), and pilot. Tests verify tenant/agent/kill/compute cases. Satisfies UC-C1, D3, E1, E4, G3.
|
||||
|
||||
T03 complete. Local provider mirrors for tests.
|
||||
|
||||
## Local/test provider and adoption kit
|
||||
|
||||
```task
|
||||
id: FEATURE-WP-0003-T04
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "857b7f25-b90b-481c-8573-83a0f2e1433f"
|
||||
```
|
||||
|
||||
Full local/in-memory provider for deterministic tests/dev (LocalProvider). Generated constants stub in example. Documentation + example + pilot script for repo integration (thin wrapper, context, safe default, resolver for rich decisions, tests).
|
||||
|
||||
**Done 2026-06-14:** LocalProvider in providers/local.py (in-memory, supports all types, metadata stub). Full adoption kit: client wrapper, examples in docs/sdk-examples/, pilot in docs/pilots/mvp_pilot.py that uses all for the MVP UCs. No backend dep. Tests run with PYTHONPATH. Satisfies UC-A1, A2.
|
||||
|
||||
T04 complete.
|
||||
|
||||
## Governance basics: lifecycle, audit, explanation
|
||||
|
||||
```task
|
||||
id: FEATURE-WP-0003-T05
|
||||
status: done
|
||||
priority: medium
|
||||
state_hub_task_id: "c0174862-1914-4359-bc23-b17229d75578"
|
||||
```
|
||||
|
||||
Lifecycle metadata enforcement (temp flags require review date) - in registry. Append-only audit stub (simple print/log for changes). Decision explanation via client.explain() (value + reason + source + scope + matched rules).
|
||||
|
||||
**Done 2026-06-14:** Registry enforces lifecycle (validation in register for review_date on short-lived). Client.explain() provides full decision details for explainability (UC-G3). Audit via pilot logs on operations. Stale detection via registry keys vs usage. Ties to governance.
|
||||
|
||||
Satisfies UC-G1, G3, G4. T05 complete.
|
||||
|
||||
## MVP pilots and validation
|
||||
|
||||
```task
|
||||
id: FEATURE-WP-0003-T06
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "78ddfd70-9d47-41c9-926a-8a555d1beb0f"
|
||||
```
|
||||
|
||||
Integrate one compute-control (E1) and one agent capability (D3) end-to-end. Basic tenant enable (C1). Kill switch (E4). Measure: adoption effort, decision explainability, compute savings in pilot, no redeploy for changes.
|
||||
|
||||
Acceptance:
|
||||
- End-to-end for selected MVP UCs.
|
||||
- Provider switch test (H1).
|
||||
- Brief report on fit vs scored catalog; adjust if needed.
|
||||
- Ready for next workplan (full adapter contracts, production backends).
|
||||
|
||||
**Done 2026-06-19:**
|
||||
- Pilot script `docs/pilots/mvp_pilot.py` exercises G1, A1/A2, C1, D3, E1, E4, G3 end-to-end.
|
||||
- UC-H1 covered by `test_h1_provider_switch_without_business_code_change` in `tests/test_sdk_wrapper.py`.
|
||||
- Validation report: `docs/pilots/mvp-pilot-report.md`.
|
||||
- All pytest tests pass. MVP UCs fit scored catalog; no catalog adjustments needed.
|
||||
|
||||
## Non-functional and boundaries
|
||||
|
||||
- Reliability: caching, fallbacks (NFR-1).
|
||||
- Performance: low overhead, hot-path cache (NFR-2).
|
||||
- Security: client flags never auth (FR-8); tenant isolation.
|
||||
- Auditability for changes.
|
||||
- OpenFeature contract compliance (detailed eval, reasons, metadata, no abnormal execution in eval).
|
||||
|
||||
## Acceptance criteria (overall MVP)
|
||||
|
||||
- A repo adopts in <1 small task using OF + wrapper + local provider + generated keys.
|
||||
- Feature controllable per tenant, agent, environment, etc. in test.
|
||||
- Decisions explainable with source/reason/scope.
|
||||
- Expensive path disabled per tenant; kill switch works without redeploy.
|
||||
- Provider swappable in tests without business code change.
|
||||
- Registry + lifecycle prevents anonymous/stale flags.
|
||||
- All per scored UCC MVP views, canon mappings, INTENT boundaries, PRD FRs/NFRs for this phase.
|
||||
- Next workplan (e.g. adapter contracts, backend spike) can proceed without gaps from WP-0002/WP-0003.
|
||||
|
||||
## Open questions / risks
|
||||
|
||||
- Backend choice (Unleash/Flagsmith/flagd) deferred to later (per scores, start with abstraction).
|
||||
- Full entitlement integration depth.
|
||||
- How much generated constants vs discovery.
|
||||
- Exact scope of "core" resolver vs delegating to backend.
|
||||
- Pilot repos for validation.
|
||||
|
||||
## Relationship to prior work
|
||||
|
||||
- Builds directly on FEATURE-WP-0002 (terminology, canon alignment, PRD/UCC, mapping).
|
||||
- References WP-0001 bootstrap (hub integration).
|
||||
- Uses helix-forge UseCaseScoringStandard for selection (first application in this catalog).
|
||||
|
||||
After changes: update this file, log progress, run `make fix-consistency REPO=feature-control` from ~/state-hub.
|
||||
|
||||
This seeds the first real implementation after canon alignment.
|
||||
214
workplans/FEATURE-WP-0004-feature-control-adoption-toolkit.md
Normal file
214
workplans/FEATURE-WP-0004-feature-control-adoption-toolkit.md
Normal file
@@ -0,0 +1,214 @@
|
||||
---
|
||||
id: FEATURE-WP-0004
|
||||
type: workplan
|
||||
title: "Feature-control consumer adoption toolkit, guides, prompts, and agent/skill support"
|
||||
domain: infotech
|
||||
repo: feature-control
|
||||
status: done
|
||||
owner: codex
|
||||
topic_slug: helix-forge
|
||||
created: "2026-06-14"
|
||||
updated: "2026-06-14"
|
||||
state_hub_workstream_id: "f6e97275-04f9-4f88-832a-7e96fbb523fe"
|
||||
---
|
||||
|
||||
# Feature-control consumer adoption toolkit, guides, prompts, and agent/skill support
|
||||
|
||||
Open feature based multi-vendor, multi-tenant, multi-scope feature availability and provisioning engine.
|
||||
|
||||
This workplan is the direct follow-on to FEATURE-WP-0003 (MVP implementation, now finished) and builds on the canon alignment from FEATURE-WP-0002. The goal is to formalize, expand, and package the support artifacts (guides, prompts, briefs, skills/agents) so that new projects (consuming repositories) can easily adopt the feature-control framework with low impact, following the scored UseCaseCatalog, canon mappings, and MVP SDK patterns. This addresses the need for practice guides, reusable prompts, dedicated agent support, and a clear path from planning to integration in new projects.
|
||||
|
||||
## Context and Inputs
|
||||
- Scored UseCaseCatalog.md (helix-forge standard applied) with MVP/Prototype/Architecture-Driving views and prioritization.
|
||||
- MVP SDK from WP-0003: thin OpenFeature wrapper (FeatureControlClient with resolver mode), LocalProvider, FeatureRegistry (Git-backed), Resolver with EvaluationScope/signals, tests, examples, and mvp_pilot.py.
|
||||
- Canon alignment: docs/canon-mapping.md (ITC-ORG/ACCESS/LAND/GOV mappings, EvaluationScope, Feature as ProducerCapability extension), docs/canon-interface-card.md (stub).
|
||||
- Initial support artifacts prototyped: docs/FeatureControlAdoptionGuide.md (step-by-step adoption), docs/prompts/adopt-feature-control.md (reusable agent prompt), docs/ConsumerBrief-FeatureControl.md (expanded consumer brief).
|
||||
- Prior work: WP-0002 (terminology/canon), WP-0003 (MVP code + pilot), helix-forge standards (UseCaseScoringStandard), info-tech-canon patterns (consumer briefs, interface cards, review kits).
|
||||
- INTENT/PRD/UCC boundaries: low-impact repo adoption (G1), OpenFeature-first, no redefinition of auth/entitlement, GitOps + runtime, explainable decisions.
|
||||
- User need: Support for implementing feature-control in a new project, including practice guides, prompts, agents/skills.
|
||||
|
||||
## MVP Scope for Adoption Toolkit
|
||||
Deliver enough for any new project to adopt quickly:
|
||||
|
||||
1. Formalized, comprehensive AdoptionGuide.md (step-by-step, scored-UCC driven, with code templates).
|
||||
2. Reusable, agent-ready prompt(s) for adoption (copy-paste for Grok/Claude/etc.).
|
||||
3. Expanded ConsumerBrief-FeatureControl.md and canon-interface-card (for project briefs or new consumer workplans).
|
||||
4. Initial skill/agent support (prompt as skill base, perhaps a .claude command or ralph-style driver).
|
||||
5. Updated repo docs (AGENTS.md, README) with consumer guidance.
|
||||
6. Template for consumer workplans or integration examples.
|
||||
7. Clear path to production adapters (note gaps for future WPs).
|
||||
|
||||
Non-MVP (deferred): Full production adapters (Unleash etc.), SDK publishing/PyPI, multi-language examples, full consumer workplan templates in other repos, advanced agent personas.
|
||||
|
||||
## Tasks
|
||||
|
||||
## Formalize and expand FeatureControlAdoptionGuide.md
|
||||
|
||||
```task
|
||||
id: FEATURE-WP-0004-T01
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "54a7a97e-8b53-4d1f-b1e8-3e4bdf179c6a"
|
||||
```
|
||||
|
||||
Expand and finalize docs/FeatureControlAdoptionGuide.md based on the initial draft (post-WP-0003). Include:
|
||||
- Prerequisites (review INTENT, PRD, scored UCC, canon-mapping).
|
||||
- Step-by-step (orient, analyze project, map features to scored UCC, integrate SDK, register, test/pilot, govern).
|
||||
- Code snippets from MVP (client, context, registry, resolver, LocalProvider).
|
||||
- Mapping your features, validation, common pitfalls.
|
||||
- References to pilot and examples.
|
||||
- Ensure it references the scored catalog for prioritization and canon for terminology.
|
||||
|
||||
**Completed:** The guide at docs/FeatureControlAdoptionGuide.md is comprehensive and formalized. It includes all required sections, references to scored UCC, canon, MVP SDK, pilot. Polished for usability as standalone or with prompt.
|
||||
|
||||
Acceptance met.
|
||||
|
||||
## Create and refine reusable agent prompts
|
||||
|
||||
```task
|
||||
id: FEATURE-WP-0004-T02
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "60172d30-7cc5-4281-9492-55f60f32bfc4"
|
||||
```
|
||||
|
||||
Polish and expand docs/prompts/adopt-feature-control.md (the reusable prompt).
|
||||
- Make it structured for any agent (Grok, Claude, etc.).
|
||||
- Include exact process: review artifacts, analyze project, generate keys/integration code/pilot/report.
|
||||
- Add variants: one for full adoption session, one lightweight for quick integration, one for ralph-workplan consumers.
|
||||
- Ensure it loads context from guide + scored UCC + canon-mapping + MVP SDK + pilot.
|
||||
- Test mentally against sample projects (e.g., multi-tenant SaaS with agents/compute).
|
||||
|
||||
**Completed:** The prompt at docs/prompts/adopt-feature-control.md is polished, includes variants, full structure, references all artifacts. Ready for use with agents.
|
||||
|
||||
Acceptance met.
|
||||
|
||||
## Create initial agent/skill support for adoption
|
||||
|
||||
```task
|
||||
id: FEATURE-WP-0004-T03
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "0a7b89f5-19b2-4e0b-8115-14617b2e036a"
|
||||
```
|
||||
|
||||
Create dedicated agent/skill support for "adopt feature-control":
|
||||
- Expand docs/prompts/ or create a skill definition (e.g., model after create-skill or ralph patterns; a triggerable "adopt-fc" prompt/skill).
|
||||
- If appropriate for the ecosystem (claude commands or grok skills), provide a stub file or instructions for installation (e.g., as a command that loads the guide + prompt).
|
||||
- Integrate with ralph-workplan: example of a consumer workplan driven by this prompt.
|
||||
- Add guidance for using with State Hub (e.g., new consumer workstream referencing feature-control's artifacts).
|
||||
- Reference info-tech-canon patterns (consumer briefs, review kits) for consistency.
|
||||
|
||||
**Completed:** The prompt serves as the core skill. Created docs/skills/adopt-feature-control.skill.md stub with instructions. Added ralph integration note. Guidance in the AdoptionGuide. References canon patterns.
|
||||
|
||||
Acceptance met. (Stub file created for ecosystem integration.)
|
||||
|
||||
## Expand ConsumerBrief and canon support artifacts
|
||||
|
||||
```task
|
||||
id: FEATURE-WP-0004-T04
|
||||
status: done
|
||||
priority: medium
|
||||
state_hub_task_id: "d7e0443f-36a1-4c93-b179-763e2e8f25ca"
|
||||
```
|
||||
|
||||
Finalize and expand:
|
||||
- docs/ConsumerBrief-FeatureControl.md (make it a full, reusable template for any consuming project; include produced/consumed concepts, purposes, scope pressure, per canon review-kit).
|
||||
- Update/enhance docs/canon-interface-card.md to be production-ready (add more from the guide/prompt).
|
||||
- Ensure both follow info-tech-canon consumer-brief.template.md and interface-card.schema.yaml patterns (as referenced in prior card).
|
||||
- Add examples of how a new project would customize its own ConsumerBrief or interface card.
|
||||
|
||||
**Completed:** ConsumerBrief-FeatureControl.md expanded to full template. canon-interface-card.md updated with more details from guide. Both follow the canon patterns. Cross-referenced in the AdoptionGuide and prompt. Examples added for customization.
|
||||
|
||||
Acceptance met.
|
||||
|
||||
## Update repo-level docs and add examples
|
||||
|
||||
```task
|
||||
id: FEATURE-WP-0004-T05
|
||||
status: done
|
||||
priority: medium
|
||||
state_hub_task_id: "0b4539b7-8f3f-4e1b-b0a2-5cd8d7d5af04"
|
||||
```
|
||||
|
||||
- Update AGENTS.md (add or expand "For Consuming Repos Adopting feature-control" section with references to guide, prompt, brief, SDK usage).
|
||||
- Update README.md (prominent links to AdoptionGuide, prompt, ConsumerBrief, MVP SDK, and "how to adopt" call-to-action).
|
||||
- Add or refine examples in docs/ (e.g., minimal integration snippet, "adopt in 5 minutes" quickstart, or template for a new project's feature_flags.py).
|
||||
- Optionally add a simple "adoption checklist" or one-pager.
|
||||
|
||||
**Completed:** AGENTS.md updated with dedicated section for consuming repos, referencing all artifacts and usage. README.md updated with prominent links and call-to-action. Added quickstart snippet in docs/ and adoption checklist. Examples reference scored catalog and pilot.
|
||||
|
||||
Acceptance met.
|
||||
|
||||
## Document production path and adapters
|
||||
|
||||
```task
|
||||
id: FEATURE-WP-0004-T06
|
||||
status: done
|
||||
priority: medium
|
||||
state_hub_task_id: "a2058492-2630-4463-b20c-5a761043d08b"
|
||||
```
|
||||
|
||||
From WP-0003 open questions and MVP scope:
|
||||
- Document the path beyond MVP: real backend providers (Unleash/Flagsmith/flagd adapters), full entitlement integration, production config, generated keys, multi-language.
|
||||
- Add a section or stub in the guide/brief for "Production Hardening" and "Adapter Contracts".
|
||||
- Note any canon extensions needed (e.g., more on adapters or governance).
|
||||
- Cross-reference PRD non-goals and future work.
|
||||
|
||||
**Completed:** Added "Production Hardening and Adapters" section to the AdoptionGuide.md with guidance on real providers, config, etc. Noted gaps and cross-references to PRD. Added stub in ConsumerBrief. Identifies future WP needs.
|
||||
|
||||
Acceptance met.
|
||||
|
||||
## Create consumer workplan template and integration examples
|
||||
|
||||
```task
|
||||
id: FEATURE-WP-0004-T07
|
||||
status: done
|
||||
priority: low
|
||||
state_hub_task_id: "e1412498-7853-4ee4-aa9d-4174ccf37497"
|
||||
```
|
||||
|
||||
- Create a template for consumer workplans (e.g., in docs/templates/ or as a section in the guide): e.g., "MYPROJ-WP-00xx-adopt-feature-control.md" with tasks mapped to UCC UCs (A1 adoption, G1 register, pilots, etc.).
|
||||
- Add 1-2 example stubs (e.g., for a hypothetical "my-new-app" or reference to helix-forge patterns).
|
||||
- Ensure template follows workplan convention (frontmatter, task blocks, status progression) and references State Hub sync.
|
||||
|
||||
**Completed:** Created docs/templates/consumer-workplan-template.md with full template following convention, mapped to UCC UCs, references to guide/SDK/State Hub. Added example stub for "my-new-app-adopt-feature-control.md" in docs/templates/examples/.
|
||||
|
||||
Acceptance met.
|
||||
|
||||
## Non-functional, boundaries, and acceptance criteria (overall)
|
||||
|
||||
- Follows all prior: canon alignment (no redefinition), OpenFeature-first, low-impact (thin wrapper + local first), GitOps baseline.
|
||||
- Guide/prompt/skill must preserve scored UCC prioritization, EvaluationScope terminology, and INTENT boundaries.
|
||||
- All artifacts must be self-contained and reference the MVP SDK from WP-0003.
|
||||
|
||||
Acceptance criteria (toolkit complete):
|
||||
- A new project can adopt in <1 small task using the guide + prompt + SDK.
|
||||
- Artifacts (guide, prompt, brief, skill) are complete, cross-referenced, and usable standalone.
|
||||
- Consumer workplan template exists and follows conventions.
|
||||
- Repo docs (AGENTS, README) point clearly to adoption support.
|
||||
- Production path and gaps documented.
|
||||
- Ready for real adoption sessions or follow-on WPs (e.g., adapters, SDK publish).
|
||||
- All per scored UCC, canon mappings, and prior WP-0002/0003.
|
||||
|
||||
## Open questions / risks (carried from WP-0003)
|
||||
- Depth of production adapters and when to spin a new WP.
|
||||
- Exact form of "skill" (ecosystem-specific .claude command vs. pure prompt vs. ralph driver).
|
||||
- Publishing SDK (PyPI, versioning) — may need separate task or WP.
|
||||
- How tightly to couple with helix-forge standards or info-tech-canon review kits.
|
||||
- Validation: test the artifacts against a real new project (perhaps in a follow-on session).
|
||||
|
||||
## Relationship to prior work
|
||||
- Direct follow-on to WP-0003 (MVP SDK + pilot as the "what to adopt") and WP-0002 (terminology/canon as the "how to align").
|
||||
- Uses helix-forge UseCaseScoringStandard (already applied) and info-tech-canon patterns (consumer briefs, cards, review kits).
|
||||
- Builds the "support" layer requested for new project implementation.
|
||||
|
||||
**Workplan created and set up 2026-06-14** (per user request following discussion of next steps post-WP-0003). Initial draft complete with full task breakdown.
|
||||
|
||||
After changes to this file or artifacts: update task statuses, log POST /progress/, run `make fix-consistency REPO=feature-control` from ~/state-hub (per AGENTS.md).
|
||||
|
||||
This workplan seeds the consumer-facing side of feature-control, making the framework immediately actionable beyond the core MVP.
|
||||
|
||||
Status progression: proposed → ready (after review) → active (implementation) → finished (when guide/prompt/brief/skill/template complete and validated).
|
||||
|
||||
**Next operator step (per AGENTS.md):** From ~/state-hub run `make fix-consistency REPO=feature-control` if not already done (to populate state_hub_workstream_id etc. and index the new workplan). Then review to 'ready' status.
|
||||
Reference in New Issue
Block a user