Private
Public Access
0
0

feat(directives): scavenge sweep 2/5 batch 3 (chronology v2 + MMA quarantine): 9 directives

This commit is contained in:
2026-07-04 01:56:35 -04:00
parent a4e1d7d1b2
commit 694000f83f
18 changed files with 90 additions and 0 deletions
@@ -0,0 +1,9 @@
# chronology_must_regenerate_after_every_track_ship
## v1
**Why this iteration:** Lifted from `docs/superpowers/specs/2026-07-01-chronology-v2-redo-design.md` §"Revision 5 — workflow.md maintenance rule" (lines 196-218). The v1 chronology desynced within days because nobody regenerated it after new tracks shipped — there was no maintenance plan. The v2 design encodes the cadence as a workflow rule: after every track ships (completion commit + `TRACK_COMPLETION_<track>.md` report), the implementing agent runs `uv run python scripts/audit/generate_chronology.py` to regenerate `conductor/chronology.md`. The regeneration is a single atomic commit (`docs(chronology): regenerate after <track-id> shipped`). If the diff goes beyond the new row (status drift on an unrelated row), the agent must investigate before committing — drift indicates a stale classifier, not a chronology bug. Regeneration is a per-track-shipping obligation, not a one-shot.
**Source:** `docs/superpowers/specs/2026-07-01-chronology-v2-redo-design.md:196-218`
---
**Lifted:** 2026-07-03 (scavenge sweep batch 2/5: docs/superpowers/specs/)
@@ -0,0 +1 @@
# Regenerate `conductor/chronology.md` after every track ships as an atomic commit
@@ -0,0 +1,9 @@
# classifier_must_emit_per_row_evidence
## v1
**Why this iteration:** Lifted from `docs/superpowers/specs/2026-07-01-chronology-v2-redo-design.md` §"scripts/audit/chronology_quality_gate.py (new)" (lines 304-321). The v2 quality gate explicitly checks "Per-row evidence: every row must have a non-empty reason from the classifier; if any row has no reason, exit 1." A classifier that returns just a status string ("Completed", "Needs Review") without the evidence that justified it is unauditable; the user cannot tell why a row got the classification it got. The fix is structural: every classification row carries a `(status, confidence, reason)` triple where `reason` names the specific evidence (e.g., "completion report found", "N work commits", "classifier inconclusive"). The reason is what makes the classifier auditable rather than trusted-on-faith.
**Source:** `docs/superpowers/specs/2026-07-01-chronology-v2-redo-design.md:304-321`
---
**Lifted:** 2026-07-03 (scavenge sweep batch 2/5: docs/superpowers/specs/)
@@ -0,0 +1 @@
# Every row produced by a classifier must carry a non-empty `reason` field naming the evidence that justified the classification
@@ -0,0 +1,9 @@
# generation_script_walks_filesystem_fresh_each_run
## v1
**Why this iteration:** Lifted from `docs/superpowers/specs/2026-07-01-chronology-v2-redo-design.md` §"Revision 1 — The desync gap (regenerate from current filesystem)" (lines 107-123). The v2 chronology was specced against a 2026-06-19 filesystem snapshot; by the time the redo track started 12 days later, the snapshot was stale — 14+ new tracks had shipped and the snapshot missed them all. The fix: the generation script (`scripts/audit/generate_chronology.py`) walks `conductor/tracks/` + `conductor/archive/` fresh on every invocation. No pinned snapshot date, no cached file list, no "last generation" timestamp filter. The principle generalizes: any script that produces a project-wide index (track list, doc cross-reference table, file inventory) must read the live filesystem, not a cached snapshot. The first pass after a snapshot-pin mistake is always incomplete.
**Source:** `docs/superpowers/specs/2026-07-01-chronology-v2-redo-design.md:107-123`
---
**Lifted:** 2026-07-03 (scavenge sweep batch 2/5: docs/superpowers/specs/)
@@ -0,0 +1 @@
# Generation/index scripts must walk the filesystem fresh on every run, never pin to a historical snapshot
@@ -0,0 +1,9 @@
# quality_gate_catches_broken_classifier_before_ship
## v1
**Why this iteration:** Lifted from `docs/superpowers/specs/2026-07-01-chronology-v2-redo-design.md` §"scripts/audit/chronology_quality_gate.py (new)" (lines 304-321) + §"Quality gate" (lines 213-216). v1 had no quality gate — the chronology shipped with 167/216 rows misclassified and nobody caught it before merge. v2 adds `scripts/audit/chronology_quality_gate.py` with 4 checks: (1) `Needs Review` threshold (fail if >30% of rows are unclassified), (2) status distribution sanity (fail if 0 rows are Completed — classifier is misclassifying everything), (3) summary quality (fail if >20% of summaries contain metadata-field text), (4) per-row evidence (fail if any row has no reason). Default mode informational (exit 0, prints report); `--strict` mode is the CI gate (exit 1 on any violation). Every audit script that classifies or summarizes data must have the same shape: a default informational mode for humans + a `--strict` CI gate that catches broken output before it ships.
**Source:** `docs/superpowers/specs/2026-07-01-chronology-v2-redo-design.md:213-216 + 304-321`
---
**Lifted:** 2026-07-03 (scavenge sweep batch 2/5: docs/superpowers/specs/)
@@ -0,0 +1 @@
# Audit scripts that classify or summarize must have a `--strict` quality gate that blocks shipping on broken output
@@ -0,0 +1,9 @@
# quarantine_flag_the_engine_not_shared_types
## v1
**Why this iteration:** Lifted from `docs/superpowers/specs/2026-07-01-mma-quarantine-rag-test-decoupling-design.md` §"The shared-types finding (why this is quarantine, not removal)" (lines 21-31) + §"1.4 What stays active (shared types, NOT gated)" (lines 90-95). The naive quarantine approach would gate the entire `src/mma.py` module behind a flag — but `mma.py` exports `Ticket`, `Track`, `TrackState`, `TrackMetadata`, `WorkerContext`, and `ThinkingSegment`, all of which are used by non-MMA code (`thinking_parser.py`, `project_manager.py`, `models.py`, `dag_engine.py`, `conductor_tech_lead.py`). Gating the types would break the conductor track system itself. The fix: gate only the engine (`ConductorEngine`, `WorkerPool`, `multi_agent_conductor.py` instantiation paths) behind the flag; keep the shared types live and importable by every consumer. The flag is a runtime check at instantiation, not an import-time gate on the module.
**Source:** `docs/superpowers/specs/2026-07-01-mma-quarantine-rag-test-decoupling-design.md:21-31 + 90-95`
---
**Lifted:** 2026-07-03 (scavenge sweep batch 2/5: docs/superpowers/specs/)
@@ -0,0 +1 @@
# When quarantining a feature, gate the engine — not the shared types module it lives in
@@ -0,0 +1,9 @@
# runtime_config_flag_vs_test_env_var_gate
## v1
**Why this iteration:** Lifted from `docs/superpowers/specs/2026-07-01-mma-quarantine-rag-test-decoupling-design.md` §"1.1 MMA Quarantine" + §"1.6 Tests (env-gated, opt-in)" (lines 44-103). When quarantining a feature, two separate flags are needed: (a) a **runtime config flag** (`mma.enabled` in `[ai_settings.toml]`, default `false`, exposed as a GUI checkbox in AI Settings) — controls whether the feature runs at runtime; persistent preference, off-by-default for new projects; per `feature_flags.md` §2 the correct pattern for a persistent on/off preference. (b) a **test opt-in env var** (`SLOP_MMA_TESTS=1` via `@pytest.mark.skipif`) — controls whether the feature's tests run in CI; default-skip because the feature is off-by-default. The two flags must NOT be conflated: a user who turns the feature on should not have to set the test env var to make the tests run; a CI runner that wants to test the feature should set the test env var without flipping the user's runtime config. Per `feature_flags.md` §6: layered flags = file presence / config for runtime, env var for test opt-in.
**Source:** `docs/superpowers/specs/2026-07-01-mma-quarantine-rag-test-decoupling-design.md:44-103`
---
**Lifted:** 2026-07-03 (scavenge sweep batch 2/5: docs/superpowers/specs/)
@@ -0,0 +1 @@
# Layered feature flags: runtime config flag (per-project persistent preference) vs test opt-in env var (separate concern)
@@ -0,0 +1,9 @@
# test_classification_via_import_presence
## v1
**Why this iteration:** Lifted from `docs/superpowers/specs/2026-07-01-mma-quarantine-rag-test-decoupling-design.md` §"1.6 Tests (env-gated, opt-in)" + §"Tier 1 — Unit tests" + §"Tier 3 — Integration tests" (lines 102-119 + 127-149). When quarantining a feature, the test classification question — "is this test an opt-in integration test, or part of the default batch?" — has a deterministic answer: does the test `import` or `instantiate` the gated engine class (e.g., `multi_agent_conductor.ConductorEngine` / `WorkerPool`)? If yes → env-gated, opt-in. If no (the test exercises only the shared types layer or mocks the engine) → stays in the default batch. The classifier is mechanical (grep for the engine class name in the test's imports + instantiations), not a per-file judgment call. This keeps the quarantine from accidentally gating tests that don't depend on the quarantined behavior, and keeps opt-in from accidentally catching tests that do.
**Source:** `docs/superpowers/specs/2026-07-01-mma-quarantine-rag-test-decoupling-design.md:102-119 + 127-149`
---
**Lifted:** 2026-07-03 (scavenge sweep batch 2/5: docs/superpowers/specs/)
@@ -0,0 +1 @@
# Classify a test as quarantined/opt-in based on whether it imports or instantiates the gated engine class
@@ -0,0 +1,9 @@
# three_tier_test_strategy_for_fragile_subsystems
## v1
**Why this iteration:** Lifted from `docs/superpowers/specs/2026-07-01-mma-quarantine-rag-test-decoupling-design.md` §"Section 2: RAG Test Decoupling" (lines 121-157). The RAG test debugging churn (10 commits, 2 ADDENDUM reports in 2026-06-27) was caused by tests that exercised RAG against the live_gui subprocess + real chromadb file locks + CWD drift, instead of against the actual algorithm. The fix is a 3-tier reclassification: **Tier 1 (unit)** tests the algorithm against the mock provider, no chromadb, no subprocess — default batch, milliseconds; **Tier 2 (controller-mock)** tests `app_controller.py` lifecycle wiring using a stub `RAGEngine` — default batch, no chromadb; **Tier 3 (integration)** is the env-gated opt-in (`@pytest.mark.skipif(SLOP_RAG_INTEGRATION != "1")`) test against real chromadb + live_gui. The default batch stops bleeding on subsystem environment fragility; Tier 3 only runs on explicit opt-in. The pattern generalizes to any subsystem where the real-environment cost (chromadb locks, subprocess state, file IO) outweighs the value of testing against the real thing in CI.
**Source:** `docs/superpowers/specs/2026-07-01-mma-quarantine-rag-test-decoupling-design.md:121-157`
---
**Lifted:** 2026-07-03 (scavenge sweep batch 2/5: docs/superpowers/specs/)
@@ -0,0 +1 @@
# Fragile subsystems (chromadb, RAG, subprocess state) must use a 3-tier test strategy: unit / controller-mock / env-gated integration
@@ -0,0 +1,9 @@
# use_git_history_as_classification_source_of_truth
## v1
**Why this iteration:** Lifted from `docs/superpowers/specs/2026-07-01-chronology-v2-redo-design.md` §"What v1 Got Wrong" + §"The new classifier" (lines 27-49 + 266-298). The chronology v1 classifier read `metadata.json.status` and got 167/216 rows wrong because the field is a snapshot set at track creation and rarely updated when work completes or is abandoned. The v2 classifier uses git history (`git log --oneline -- <folder>`) as the audit log: count work commits (`feat/fix/refactor/perf/test/docs(report):`) per folder, override with completion/abort reports in `docs/reports/`, fall back to directory location. Git history is the project's audit log; metadata files are snapshots that drift. The principle generalizes: any status classification (track state, ticket state, file liveness) should be backed by immutable evidence (git, files on disk), not by editable metadata.
**Source:** `docs/superpowers/specs/2026-07-01-chronology-v2-redo-design.md:27-49 + 266-298`
---
**Lifted:** 2026-07-03 (scavenge sweep batch 2/5: docs/superpowers/specs/)
@@ -0,0 +1 @@
# Status classifiers must use git history (commit log) as the source of truth, not stale metadata.json fields