@aperant/framework 0.17.0 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +261 -0
- package/agents/apt-executor.md +6 -0
- package/agents/apt-planner.md +3 -2
- package/bin/features-reconcile-check.mjs +77 -0
- package/dist/cli/artifacts/self-stage.d.mts.map +1 -1
- package/dist/cli/artifacts/self-stage.mjs +2 -1
- package/dist/cli/artifacts/self-stage.mjs.map +1 -1
- package/dist/cli/cli-wrappers/features-reconcile.d.mts +2 -0
- package/dist/cli/cli-wrappers/features-reconcile.d.mts.map +1 -0
- package/dist/cli/cli-wrappers/features-reconcile.mjs +9 -0
- package/dist/cli/cli-wrappers/features-reconcile.mjs.map +1 -0
- package/dist/cli/commands/ci-watch.mjs +49 -2
- package/dist/cli/commands/ci-watch.mjs.map +1 -1
- package/dist/cli/commands/commit.mjs +3 -3
- package/dist/cli/commands/commit.mjs.map +1 -1
- package/dist/cli/commands/event.mjs +16 -16
- package/dist/cli/commands/event.mjs.map +1 -1
- package/dist/cli/commands/features-reconcile.d.mts +2 -0
- package/dist/cli/commands/features-reconcile.d.mts.map +1 -0
- package/dist/cli/commands/features-reconcile.mjs +143 -0
- package/dist/cli/commands/features-reconcile.mjs.map +1 -0
- package/dist/cli/commands/health-check.d.mts +2 -2
- package/dist/cli/commands/health-check.mjs +2 -2
- package/dist/cli/commands/merge-integrate.mjs +3 -3
- package/dist/cli/commands/merge-integrate.mjs.map +1 -1
- package/dist/cli/commands/produce.d.mts +9 -0
- package/dist/cli/commands/produce.d.mts.map +1 -0
- package/dist/cli/commands/produce.mjs +1345 -0
- package/dist/cli/commands/produce.mjs.map +1 -0
- package/dist/cli/commands/task.d.mts +16 -1
- package/dist/cli/commands/task.d.mts.map +1 -1
- package/dist/cli/commands/task.mjs +434 -266
- package/dist/cli/commands/task.mjs.map +1 -1
- package/dist/cli/coordination/auto-emit-artifact-ready.mjs +5 -5
- package/dist/cli/coordination/auto-emit-artifact-ready.mjs.map +1 -1
- package/dist/cli/coordination/event-schema.d.mts +5 -3
- package/dist/cli/coordination/event-schema.d.mts.map +1 -1
- package/dist/cli/coordination/event-schema.mjs +245 -21
- package/dist/cli/coordination/event-schema.mjs.map +1 -1
- package/dist/cli/coordination/store.d.mts +2 -2
- package/dist/cli/coordination/store.mjs +4 -4
- package/dist/cli/coordination/store.mjs.map +1 -1
- package/dist/cli/dispatch.d.mts.map +1 -1
- package/dist/cli/dispatch.mjs +4 -2
- package/dist/cli/dispatch.mjs.map +1 -1
- package/dist/cli/features/area-shape.d.mts +11 -0
- package/dist/cli/features/area-shape.d.mts.map +1 -0
- package/dist/cli/features/area-shape.mjs +141 -0
- package/dist/cli/features/area-shape.mjs.map +1 -0
- package/dist/cli/features/delta.d.mts +78 -0
- package/dist/cli/features/delta.d.mts.map +1 -0
- package/dist/cli/features/delta.mjs +591 -0
- package/dist/cli/features/delta.mjs.map +1 -0
- package/dist/cli/features/reconcile.d.mts +236 -0
- package/dist/cli/features/reconcile.d.mts.map +1 -0
- package/dist/cli/features/reconcile.mjs +1126 -0
- package/dist/cli/features/reconcile.mjs.map +1 -0
- package/dist/cli/features/surface-map.d.mts +63 -0
- package/dist/cli/features/surface-map.d.mts.map +1 -0
- package/dist/cli/features/surface-map.mjs +191 -0
- package/dist/cli/features/surface-map.mjs.map +1 -0
- package/dist/cli/{commands/features-audit.d.mts → features/write-root.d.mts} +4 -3
- package/dist/cli/features/write-root.d.mts.map +1 -0
- package/dist/cli/features/write-root.mjs +137 -0
- package/dist/cli/features/write-root.mjs.map +1 -0
- package/dist/cli/gate/gates/features-reconciled.d.mts +36 -0
- package/dist/cli/gate/gates/features-reconciled.d.mts.map +1 -0
- package/dist/cli/gate/gates/features-reconciled.mjs +67 -0
- package/dist/cli/gate/gates/features-reconciled.mjs.map +1 -0
- package/dist/cli/gate/gates/index.mjs +1 -0
- package/dist/cli/gate/gates/index.mjs.map +1 -1
- package/dist/cli/help.d.mts.map +1 -1
- package/dist/cli/help.mjs +31 -1
- package/dist/cli/help.mjs.map +1 -1
- package/dist/cli/install/legacy-paths.d.mts.map +1 -1
- package/dist/cli/install/legacy-paths.mjs +2 -0
- package/dist/cli/install/legacy-paths.mjs.map +1 -1
- package/dist/cli/produce/blind-probe.d.mts +85 -0
- package/dist/cli/produce/blind-probe.d.mts.map +1 -0
- package/dist/cli/produce/blind-probe.mjs +217 -0
- package/dist/cli/produce/blind-probe.mjs.map +1 -0
- package/dist/cli/produce/claim.d.mts +188 -0
- package/dist/cli/produce/claim.d.mts.map +1 -0
- package/dist/cli/produce/claim.mjs +518 -0
- package/dist/cli/produce/claim.mjs.map +1 -0
- package/dist/cli/produce/done-gate.d.mts +87 -0
- package/dist/cli/produce/done-gate.d.mts.map +1 -0
- package/dist/cli/produce/done-gate.mjs +200 -0
- package/dist/cli/produce/done-gate.mjs.map +1 -0
- package/dist/cli/produce/events.d.mts +77 -0
- package/dist/cli/produce/events.d.mts.map +1 -0
- package/dist/cli/produce/events.mjs +126 -0
- package/dist/cli/produce/events.mjs.map +1 -0
- package/dist/cli/produce/evidence-oracle.d.mts +63 -0
- package/dist/cli/produce/evidence-oracle.d.mts.map +1 -0
- package/dist/cli/produce/evidence-oracle.mjs +122 -0
- package/dist/cli/produce/evidence-oracle.mjs.map +1 -0
- package/dist/cli/produce/ledger.d.mts +140 -0
- package/dist/cli/produce/ledger.d.mts.map +1 -0
- package/dist/cli/produce/ledger.mjs +272 -0
- package/dist/cli/produce/ledger.mjs.map +1 -0
- package/dist/cli/produce/probe-family.d.mts +53 -0
- package/dist/cli/produce/probe-family.d.mts.map +1 -0
- package/dist/cli/produce/probe-family.mjs +160 -0
- package/dist/cli/produce/probe-family.mjs.map +1 -0
- package/dist/cli/produce/projection.d.mts +55 -0
- package/dist/cli/produce/projection.d.mts.map +1 -0
- package/dist/cli/produce/projection.mjs +97 -0
- package/dist/cli/produce/projection.mjs.map +1 -0
- package/dist/cli/produce/run-id.d.mts +42 -0
- package/dist/cli/produce/run-id.d.mts.map +1 -0
- package/dist/cli/produce/run-id.mjs +79 -0
- package/dist/cli/produce/run-id.mjs.map +1 -0
- package/dist/cli/produce/saga.d.mts +180 -0
- package/dist/cli/produce/saga.d.mts.map +1 -0
- package/dist/cli/produce/saga.mjs +290 -0
- package/dist/cli/produce/saga.mjs.map +1 -0
- package/dist/cli/produce/scheduler.d.mts +165 -0
- package/dist/cli/produce/scheduler.d.mts.map +1 -0
- package/dist/cli/produce/scheduler.mjs +399 -0
- package/dist/cli/produce/scheduler.mjs.map +1 -0
- package/dist/cli/produce/setpoint.d.mts +52 -0
- package/dist/cli/produce/setpoint.d.mts.map +1 -0
- package/dist/cli/produce/setpoint.mjs +113 -0
- package/dist/cli/produce/setpoint.mjs.map +1 -0
- package/dist/cli/produce/verification-ttl.d.mts +75 -0
- package/dist/cli/produce/verification-ttl.d.mts.map +1 -0
- package/dist/cli/produce/verification-ttl.mjs +169 -0
- package/dist/cli/produce/verification-ttl.mjs.map +1 -0
- package/dist/cli/release-notes/ship-autodraft.mjs +2 -2
- package/dist/cli/roadmap/{conductor-view.d.mts → showrunner-view.d.mts} +3 -3
- package/dist/cli/roadmap/showrunner-view.d.mts.map +1 -0
- package/dist/cli/roadmap/{conductor-view.mjs → showrunner-view.mjs} +7 -7
- package/dist/cli/roadmap/showrunner-view.mjs.map +1 -0
- package/dist/cli/variant/gallery.d.mts.map +1 -1
- package/dist/cli/variant/gallery.mjs +7 -3
- package/dist/cli/variant/gallery.mjs.map +1 -1
- package/dist/plugin/.claude-plugin/plugin.json +2 -1
- package/dist/plugin/agents/apt-executor.md +6 -0
- package/dist/plugin/agents/apt-planner.md +3 -2
- package/dist/plugin/skills/apt/SKILL.md +112 -38
- package/dist/plugin/skills/apt-close-task/SKILL.md +2 -2
- package/dist/plugin/skills/apt-debug/SKILL.md +22 -24
- package/dist/plugin/skills/apt-execute/SKILL.md +35 -26
- package/dist/plugin/skills/apt-fan-out/SKILL.md +4 -4
- package/dist/plugin/skills/apt-handoff/SKILL.md +1 -1
- package/dist/plugin/skills/apt-mockup/SKILL.md +1 -1
- package/dist/plugin/skills/apt-plan/SKILL.md +5 -5
- package/dist/plugin/skills/apt-plan/adapters/{conductor.md → showrunner.md} +16 -16
- package/dist/plugin/skills/apt-produce/SKILL.md +606 -0
- package/dist/plugin/skills/apt-quick/SKILL.md +27 -33
- package/dist/plugin/skills/apt-review/SKILL.md +14 -11
- package/dist/plugin/skills/apt-run/SKILL.md +132 -3
- package/dist/plugin/skills/apt-ship/SKILL.md +29 -5
- package/dist/plugin/skills/apt-spar/SKILL.md +5 -3
- package/dist/plugin/skills/apt-watch-ci/SKILL.md +6 -4
- package/dist/schemas/feature-registry.d.ts.map +1 -1
- package/dist/schemas/feature-registry.js +34 -3
- package/dist/schemas/feature-registry.js.map +1 -1
- package/dist/types/config.d.ts +8 -5
- package/dist/types/config.d.ts.map +1 -1
- package/package.json +4 -4
- package/prompts/{conductor-framework-context.md → showrunner-framework-context.md} +1 -1
- package/prompts/{conductor-status-check.md → showrunner-status-check.md} +1 -1
- package/prompts/{conductor-sub-agent.md → showrunner-sub-agent.md} +6 -6
- package/prompts/{conductor-system.md → showrunner-system.md} +8 -8
- package/skills/apt/SKILL.md +112 -38
- package/skills/apt-close-task/SKILL.md +2 -2
- package/skills/apt-debug/SKILL.md +22 -24
- package/skills/apt-execute/SKILL.md +35 -26
- package/skills/apt-fan-out/SKILL.md +4 -4
- package/skills/apt-handoff/SKILL.md +1 -1
- package/skills/apt-mockup/SKILL.md +1 -1
- package/skills/apt-plan/SKILL.md +5 -5
- package/skills/apt-plan/adapters/{conductor.md → showrunner.md} +16 -16
- package/skills/apt-produce/SKILL.md +606 -0
- package/skills/apt-quick/SKILL.md +27 -33
- package/skills/apt-review/SKILL.md +14 -11
- package/skills/apt-run/SKILL.md +132 -3
- package/skills/apt-ship/SKILL.md +29 -5
- package/skills/apt-spar/SKILL.md +5 -3
- package/skills/apt-watch-ci/SKILL.md +6 -4
- package/src/cli/artifacts/self-stage.mjs +2 -1
- package/src/cli/cli-wrappers/features-reconcile.mjs +9 -0
- package/src/cli/commands/ci-watch.mjs +51 -2
- package/src/cli/commands/commit.mjs +3 -3
- package/src/cli/commands/event.mjs +16 -16
- package/src/cli/commands/features-reconcile.mjs +157 -0
- package/src/cli/commands/health-check.mjs +2 -2
- package/src/cli/commands/merge-integrate.mjs +3 -3
- package/src/cli/commands/produce.mjs +1466 -0
- package/src/cli/commands/task.mjs +482 -285
- package/src/cli/coordination/auto-emit-artifact-ready.mjs +5 -5
- package/src/cli/coordination/event-schema.d.ts +4 -2
- package/src/cli/coordination/event-schema.mjs +276 -21
- package/src/cli/coordination/store.mjs +4 -4
- package/src/cli/dispatch.mjs +4 -2
- package/src/cli/features/area-shape.mjs +140 -0
- package/src/cli/features/delta.mjs +625 -0
- package/src/cli/features/reconcile.mjs +1169 -0
- package/src/cli/features/surface-map.mjs +192 -0
- package/src/cli/features/write-root.mjs +140 -0
- package/src/cli/gate/gates/features-reconciled.mjs +70 -0
- package/src/cli/gate/gates/index.mjs +1 -0
- package/src/cli/help.mjs +31 -1
- package/src/cli/install/legacy-paths.mjs +2 -0
- package/src/cli/produce/blind-probe.mjs +245 -0
- package/src/cli/produce/claim.mjs +543 -0
- package/src/cli/produce/done-gate.mjs +238 -0
- package/src/cli/produce/events.mjs +131 -0
- package/src/cli/produce/evidence-oracle.mjs +133 -0
- package/src/cli/produce/ledger.mjs +284 -0
- package/src/cli/produce/probe-family.mjs +168 -0
- package/src/cli/produce/projection.mjs +105 -0
- package/src/cli/produce/run-id.mjs +84 -0
- package/src/cli/produce/saga.mjs +303 -0
- package/src/cli/produce/scheduler.mjs +423 -0
- package/src/cli/produce/setpoint.mjs +122 -0
- package/src/cli/produce/verification-ttl.mjs +191 -0
- package/src/cli/release-notes/ship-autodraft.mjs +2 -2
- package/src/cli/roadmap/showrunner-view.d.ts +10 -0
- package/src/cli/roadmap/{conductor-view.mjs → showrunner-view.mjs} +6 -6
- package/src/cli/variant/gallery.mjs +7 -3
- package/templates/aperant-claude-md-appendix.md +2 -2
- package/workflows/scan-features.md +17 -11
- package/dist/cli/cli-wrappers/features-audit.d.mts +0 -2
- package/dist/cli/cli-wrappers/features-audit.d.mts.map +0 -1
- package/dist/cli/cli-wrappers/features-audit.mjs +0 -8
- package/dist/cli/cli-wrappers/features-audit.mjs.map +0 -1
- package/dist/cli/commands/features-audit.d.mts.map +0 -1
- package/dist/cli/commands/features-audit.mjs +0 -293
- package/dist/cli/commands/features-audit.mjs.map +0 -1
- package/dist/cli/features/registry-audit.d.mts +0 -56
- package/dist/cli/features/registry-audit.d.mts.map +0 -1
- package/dist/cli/features/registry-audit.mjs +0 -264
- package/dist/cli/features/registry-audit.mjs.map +0 -1
- package/dist/cli/roadmap/conductor-view.d.mts.map +0 -1
- package/dist/cli/roadmap/conductor-view.mjs.map +0 -1
- package/src/cli/cli-wrappers/features-audit.mjs +0 -8
- package/src/cli/commands/features-audit.mjs +0 -302
- package/src/cli/features/registry-audit.mjs +0 -254
- package/src/cli/roadmap/conductor-view.d.ts +0 -10
|
@@ -17,6 +17,7 @@ import './verify-approved.mjs';
|
|
|
17
17
|
import './review-clean.mjs';
|
|
18
18
|
import './followups-adjudicated.mjs';
|
|
19
19
|
import './gitignore-in-sync.mjs';
|
|
20
|
+
import './features-reconciled.mjs';
|
|
20
21
|
import './consistency-check.mjs';
|
|
21
22
|
import './tdd-iron-law.mjs';
|
|
22
23
|
import './r-persona-alignment.mjs';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sourceRoot":"","sources":["../../../../src/cli/gate/gates/index.mjs"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,yBAAyB,CAAA;AAChC,OAAO,6BAA6B,CAAA;AACpC,OAAO,mBAAmB,CAAA;AAC1B,OAAO,6BAA6B,CAAA;AACpC,OAAO,uBAAuB,CAAA;AAC9B,OAAO,oBAAoB,CAAA;AAC3B,OAAO,6BAA6B,CAAA;AACpC,OAAO,yBAAyB,CAAA;AAChC,OAAO,yBAAyB,CAAA;AAChC,OAAO,oBAAoB,CAAA;AAC3B,OAAO,2BAA2B,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.mjs","sourceRoot":"","sources":["../../../../src/cli/gate/gates/index.mjs"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,yBAAyB,CAAA;AAChC,OAAO,6BAA6B,CAAA;AACpC,OAAO,mBAAmB,CAAA;AAC1B,OAAO,6BAA6B,CAAA;AACpC,OAAO,uBAAuB,CAAA;AAC9B,OAAO,oBAAoB,CAAA;AAC3B,OAAO,6BAA6B,CAAA;AACpC,OAAO,yBAAyB,CAAA;AAChC,OAAO,2BAA2B,CAAA;AAClC,OAAO,yBAAyB,CAAA;AAChC,OAAO,oBAAoB,CAAA;AAC3B,OAAO,2BAA2B,CAAA"}
|
package/dist/cli/help.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"help.d.mts","sourceRoot":"","sources":["../../src/cli/help.mjs"],"names":[],"mappings":"AAMA,
|
|
1
|
+
{"version":3,"file":"help.d.mts","sourceRoot":"","sources":["../../src/cli/help.mjs"],"names":[],"mappings":"AAMA,kCA6KC"}
|
package/dist/cli/help.mjs
CHANGED
|
@@ -27,6 +27,7 @@ Commands:
|
|
|
27
27
|
risk-check <dir> --paths <p1> [--operation <type>] Classify file paths by risk level
|
|
28
28
|
|
|
29
29
|
task create <dir> --description <text> [--scope <s>] [--milestone <id>] [--phase <id>] [--roadmap-ref-url <url>] [--depends-on <refs>] [--track <T>] [--autonomy <N>] Create isolated task
|
|
30
|
+
task ensure <dir> --description <text> --intent <create-new|require-existing|self-managed|none> [--track <T>] [--autonomy <N>] [--scope <s>] [--id <id>] Deterministic idempotent allocator: create-new provisions a per-task worktree (idempotent on re-run), require-existing resolves the active task without minting, none/self-managed allocate nothing
|
|
30
31
|
task list <dir> [--scope <s>] [--blocked-by <id>] List active tasks (optionally filtered)
|
|
31
32
|
task get <dir> --id <task-id> Get task details and artifacts
|
|
32
33
|
task update <dir> --id <id> [--lifecycle-phase <p>] [--pr-url <url>] [--subtasks-total <N>] [--depends-on <refs>] Update non-linkage task state; --pr-url may arm ci-watch per ci_watch.after_ship
|
|
@@ -35,7 +36,7 @@ Commands:
|
|
|
35
36
|
task close-merged <dir> [--task <id>] [--narrate-only] [--dry-run] Sweep shipped-pending-merge tasks for confirmed merges (--narrate-only returns pending_narration[] entries read-only without closing).
|
|
36
37
|
task narration-drain <dir> --task <task-id> Remove a row from state.pending_narration[] under withFileLock (called by /apt:close-task --narrate-only after a successful narrator spawn)
|
|
37
38
|
task complete-subtask <dir> --task-id <id> --subtask-id <sid|a+b+c> [--commit <sha>] [--notes <text>] Atomic plan ↔ build-progress sync
|
|
38
|
-
features-
|
|
39
|
+
features-reconcile <dir> (--draft|--write|--check|--gc) [--task-id <id>] [--subtask-id <id>] [--base <ref>] [--dry-run] [--warn-only] [--max-age-days <n>] [--no-worktree-redirect] Feature-registry delta ledger: --draft scaffolds a per-writer delta from the base..HEAD diff, --write materializes deltas into area JSONs + a receipt, --check verifies coverage/schema/integrity/orphans, --gc prunes merged receipts (BUG-025b: --task-id redirects writes to active task's worktree)
|
|
39
40
|
docs-audit <dir> [--diff-files <csv>|--since <ref>|--dry-run] [--policy <path>] [--format json|md] Audit documented surfaces for docs-drift
|
|
40
41
|
|
|
41
42
|
lock claim <dir> --subtask <id> Claim exclusive lock on a subtask
|
|
@@ -134,6 +135,35 @@ Commands:
|
|
|
134
135
|
ci-watch start|stop|status|tick <dir> [--pr <N>] [...] /apt:watch-ci primitives — see SKILL.md for full flag matrix
|
|
135
136
|
ci-watch sweep <dir> --orphaned [--dry-run] BUG-027: enumerate ci-watches state files, query gh per PR, remove terminal-state (MERGED|CLOSED) entries (manual GC; rate-limited)
|
|
136
137
|
|
|
138
|
+
produce start <dir> --outcome "<o>" [--run-id <id>] /apt:produce M1 — freeze an immutable acceptance setpoint under .aperant/produce/<run-id>/ (idempotent-reuse on --run-id, never overwrites); emits produce.run.started + produce.setpoint.frozen
|
|
139
|
+
produce add-milestone <dir> --run-id <id> --title "<t>" [--id <mid>] Append produce.roadmap.milestone_added + refresh the derived roadmap.json projection cache
|
|
140
|
+
produce set-milestone-status <dir> --run-id <id> --milestone <mid> --status <planned|in_progress|done> [--verdict-path <p>] Append produce.roadmap.milestone_status_changed; --status done is the M2 two-gate adjudication (visible oracle AND blind probe)
|
|
141
|
+
produce status <dir> --run-id <id> Re-project the roadmap from the append-only event log (no in-memory authority)
|
|
142
|
+
produce tick <dir> --run-id <id> Run exactly ONE wake tick — re-project from disk, emit produce.tick, compute next_action + next_tick_hint, then exit (no loop)
|
|
143
|
+
produce record-implementer <dir> --run-id <id> --milestone <mid> --implementer-family <fam> /apt:produce M2 — record the implementer family (the cross-family disjointness anchor)
|
|
144
|
+
produce resolve-probe-family <dir> --run-id <id> [--milestone <mid>] [--implementer-family <fam>] [--host-family <fam>] [--available-families a,b,c] M2 — resolve a probe/oracle family DISJOINT from the implementer + a LIVE model (never hardcoded); available:false when none
|
|
145
|
+
produce oracle prepare <dir> --run-id <id> --milestone <mid> --verdict-path <p> M2 — extract verify-proof's v2 verdict (must be approved) + tests[] evidence into a cross-family judge payload
|
|
146
|
+
produce oracle record <dir> --run-id <id> --milestone <mid> --verdict <pass|fail> --oracle-family <fam> M2 — record produce.oracle.judged (refused when oracle_family === implementer)
|
|
147
|
+
produce probe freeze <dir> --run-id <id> --milestone <mid> --probe-file <p> --author-family <fam> M2 — freeze an immutable held-out probe set (hash + family only; refused when author_family === implementer)
|
|
148
|
+
produce probe record <dir> --run-id <id> --milestone <mid> --result <pass|fail> --probe-family <fam> --head-sha <sha> M2 — record produce.probe.run (result/family/sha only; refused when probe_family === implementer)
|
|
149
|
+
produce probe sweep <dir> --run-id <id> [--sample N] M2 — deterministic rotating sample of already-done milestones to blind-re-probe against HEAD
|
|
150
|
+
produce canary <dir> --run-id <id> M2 — green-on-visible MINUS green-on-blind + per-milestone breakdown (the reward-hacking canary)
|
|
151
|
+
produce declare-criteria <dir> --run-id <id> --milestone <mid> --criterion "<text>" [--criterion-id <cid>] [--scope-change "<reason>"] /apt:produce M3 — open one acceptance criterion (V += 1); rejected after descent unless --scope-change justifies the increase (anti-windup)
|
|
152
|
+
produce progress <dir> --run-id <id> M3 — re-read the Lyapunov V-series from the log: open-criteria count strictly decreasing across shipped milestones + any un-sanctioned-increase violations (flags, never rejects)
|
|
153
|
+
produce saga enter <dir> --run-id <id> --milestone <mid> --phase <plan|execute|verify|review|ship> /apt:produce M4 — append produce.saga.phase_entered (separate fold from the roadmap projection)
|
|
154
|
+
produce saga complete <dir> --run-id <id> --milestone <mid> --phase <plan|execute|verify|review|ship> M4 — append produce.saga.phase_completed
|
|
155
|
+
produce saga compensate <dir> --run-id <id> --milestone <mid> --phase <p> [--reason "<r>"] M4 — fire the FORWARD compensator (verify|review|ship ships a revert + reopens + re-plans; NEVER rolls back a merged PR); records the descriptor, does not execute it
|
|
156
|
+
produce saga resolve-reviewer <dir> --run-id <id> --milestone <mid> [--host-family <fam>] [--available-families a,b,c] M4 — resolve a REVIEW-phase reviewer family DISJOINT from the implementer + a LIVE model (reuses resolveProbeFamily; never hardcoded); available:false when none
|
|
157
|
+
produce saga review <dir> --run-id <id> --milestone <mid> --verdict <pass|fail> --reviewer-family <fam> M4 — record produce.saga.reviewed (refused when reviewer_family === implementer)
|
|
158
|
+
produce saga status <dir> --run-id <id> M4 — re-project per-milestone saga phase state + pending compensation from the log (no roadmap status mutation)
|
|
159
|
+
produce ttl select <dir> --run-id <id> --head-sha <sha> [--sample N] M4 — deterministic rotating sample of OLD done milestones STALE against HEAD (reuses the M2 rotation; a milestone re-verified against current HEAD is excluded as fresh)
|
|
160
|
+
produce ttl reverify <dir> --run-id <id> --milestone <mid> --result <pass|fail> --probe-family <fam> --head-sha <sha> M4 — cross-family re-verify; --result fail appends ttl.reverified + ttl.regression_detected + fires the FORWARD compensator (ships a revert, not a rollback)
|
|
161
|
+
produce schedule <dir> --run-id <id> [--wip N] /apt:produce M5 — WSJF-rank the ready milestones (cost-of-delay / job-size) + a WIP-limited pick; dependency-aware readiness (blocked / cycle), M4-regression re-entry; read-only
|
|
162
|
+
produce claim declare <dir> --run-id <id> --profile <p> --claim-file <path> [--claim-id <id>] /apt:produce M6 — validate + freeze an immutable Claim Envelope to claims/<claim-id>.json (interop, not a 4th store); rejects a global/unbounded scope, empty preconditions, or missing expiry fail-closed; logs produce.claim.declared (content_hash only)
|
|
163
|
+
produce claim list <dir> --run-id <id> M6 — re-project the claim ledger (declared − expired) folded from the append-only log; produce.claim.* never enters the roadmap projection
|
|
164
|
+
produce claim expire <dir> --run-id <id> --claim-id <id> [--reason "<r>"] M6 — append produce.claim.expired; the claim drops out of the ledger's active set (anti-corrosion manual expiry)
|
|
165
|
+
produce claim consume <dir> --run-id <id> [--milestone <mid>] M6 — emit the STRUCTURED delta {claim_id, targets:[{kind, requirement, ref?}]} derived from resolution_verifier (never a lesson-text paste); skips expired / HEAD-invalidated / precondition-unmatched claims
|
|
166
|
+
|
|
137
167
|
followups check <dir> --task-id <id> G45: derive the expected follow-up universe (Out of Scope ∪ raw review rows ∪ qa findings) + report missing/unadjudicated/unfixed/undispositioned rows; exit 1 when the ledger is dishonest
|
|
138
168
|
followups disposition <dir> --task-id <id> --row <row-id> --kind <filed_task|executed_commit|parked_note|dropped_by_user> --ref <ref> [--reason <text>] G45: flip a ledger row to dispositioned (atomic; dropped_by_user requires --reason)
|
|
139
169
|
followups policy <dir> --task-id <id> G45: effective disposition policy (ask|file|chain + max_chain_depth) from config.followups when set, else autonomy-derived
|
package/dist/cli/help.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"help.mjs","sourceRoot":"","sources":["../../src/cli/help.mjs"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAE1C,MAAM,UAAU,SAAS;IACxB,MAAM,IAAI,GAAG,GAAG,UAAU,EAAE
|
|
1
|
+
{"version":3,"file":"help.mjs","sourceRoot":"","sources":["../../src/cli/help.mjs"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAE1C,MAAM,UAAU,SAAS;IACxB,MAAM,IAAI,GAAG,GAAG,UAAU,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oBAyKT,CAAA;IAEnB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,CAAA;AAClC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"legacy-paths.d.mts","sourceRoot":"","sources":["../../../src/cli/install/legacy-paths.mjs"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH;;;;;;GAMG;AAEH,gDAAgD;AAChD,mCADW,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,
|
|
1
|
+
{"version":3,"file":"legacy-paths.d.mts","sourceRoot":"","sources":["../../../src/cli/install/legacy-paths.mjs"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH;;;;;;GAMG;AAEH,gDAAgD;AAChD,mCADW,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAwJ1C;;kBA9JY,MAAM;kBACN,MAAM;;;;;qBAEN,aAAa,CAAC,MAAM,CAAC"}
|
|
@@ -106,6 +106,7 @@ export const LEGACY_INSTALL_PATHS = Object.freeze({
|
|
|
106
106
|
'agents/apt-personas.md',
|
|
107
107
|
'agents/apt-plan.md',
|
|
108
108
|
'agents/apt-pr-review.md',
|
|
109
|
+
'agents/apt-produce.md',
|
|
109
110
|
'agents/apt-prototype.md',
|
|
110
111
|
'agents/apt-quick.md',
|
|
111
112
|
'agents/apt-release-notes.md',
|
|
@@ -151,6 +152,7 @@ export const LEGACY_INSTALL_PATHS = Object.freeze({
|
|
|
151
152
|
'commands/apt-personas.md',
|
|
152
153
|
'commands/apt-plan.md',
|
|
153
154
|
'commands/apt-pr-review.md',
|
|
155
|
+
'commands/apt-produce.md',
|
|
154
156
|
'commands/apt-prototype.md',
|
|
155
157
|
'commands/apt-quick.md',
|
|
156
158
|
'commands/apt-release-notes.md',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"legacy-paths.mjs","sourceRoot":"","sources":["../../../src/cli/install/legacy-paths.mjs"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"legacy-paths.mjs","sourceRoot":"","sources":["../../../src/cli/install/legacy-paths.mjs"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/** The probes/<milestone>.json path for a run + milestone. */
|
|
2
|
+
export function probeSetPathFor(projectDir: any, runId: any, milestoneId: any): string;
|
|
3
|
+
/** Read + parse a frozen probe set. Returns null when absent or malformed. */
|
|
4
|
+
export function readProbeSet(projectDir: any, runId: any, milestoneId: any): any;
|
|
5
|
+
/**
|
|
6
|
+
* Freeze a blind-probe set for a milestone, idempotently. REFUSES fail-closed
|
|
7
|
+
* when the author family equals the implementer family (a held-out probe an
|
|
8
|
+
* implementer authored is not held out — ID-06) or when no implementer family
|
|
9
|
+
* is recorded (ID-M2-02). On a FRESH freeze appends `produce.probe.frozen`
|
|
10
|
+
* carrying ONLY the hash + author family (never the content). A second freeze
|
|
11
|
+
* returns the byte-identical stored set (`reused: true`) and never re-logs.
|
|
12
|
+
*
|
|
13
|
+
* @param {string} projectDir
|
|
14
|
+
* @param {string} runId
|
|
15
|
+
* @param {string} milestoneId
|
|
16
|
+
* @param {{ content: unknown, authorFamily: string, implementerFamily: string }} args
|
|
17
|
+
* @param {Date} [now]
|
|
18
|
+
* @returns {{ ok: true, reused: boolean, probe_set_hash: string, author_family: string }
|
|
19
|
+
* | { ok: false, reason: string }}
|
|
20
|
+
*/
|
|
21
|
+
export function freezeProbeSet(projectDir: string, runId: string, milestoneId: string, { content, authorFamily, implementerFamily }: {
|
|
22
|
+
content: unknown;
|
|
23
|
+
authorFamily: string;
|
|
24
|
+
implementerFamily: string;
|
|
25
|
+
}, now?: Date): {
|
|
26
|
+
ok: true;
|
|
27
|
+
reused: boolean;
|
|
28
|
+
probe_set_hash: string;
|
|
29
|
+
author_family: string;
|
|
30
|
+
} | {
|
|
31
|
+
ok: false;
|
|
32
|
+
reason: string;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Record a blind-probe RUN result. REFUSES fail-closed when the probe family
|
|
36
|
+
* equals the implementer family (a probe run BY the implementer family is not
|
|
37
|
+
* cross-family — ID-08) or when no implementer family is recorded. On
|
|
38
|
+
* acceptance appends `produce.probe.run {run_id, milestone_id, result,
|
|
39
|
+
* probe_family, head_sha}` — result/family/head_sha only, never content.
|
|
40
|
+
*
|
|
41
|
+
* @param {string} projectDir
|
|
42
|
+
* @param {{ runId: string, milestoneId: string, result: string, probeFamily: string, headSha: string }} args
|
|
43
|
+
* @returns {{ ok: true, result: string, probe_family: string, head_sha: string }
|
|
44
|
+
* | { ok: false, reason: string }}
|
|
45
|
+
*/
|
|
46
|
+
export function recordProbeRun(projectDir: string, { runId, milestoneId, result, probeFamily, headSha }: {
|
|
47
|
+
runId: string;
|
|
48
|
+
milestoneId: string;
|
|
49
|
+
result: string;
|
|
50
|
+
probeFamily: string;
|
|
51
|
+
headSha: string;
|
|
52
|
+
}): {
|
|
53
|
+
ok: true;
|
|
54
|
+
result: string;
|
|
55
|
+
probe_family: string;
|
|
56
|
+
head_sha: string;
|
|
57
|
+
} | {
|
|
58
|
+
ok: false;
|
|
59
|
+
reason: string;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Select a DETERMINISTIC rotating sample of already-`done` milestones for blind
|
|
63
|
+
* re-probing against HEAD (US-6). Rotates by fewest prior probe runs first,
|
|
64
|
+
* then oldest last-probe-run first (a never-probed done milestone sorts first),
|
|
65
|
+
* then first-seen roadmap order — so two folds of the same log select the same
|
|
66
|
+
* sample.
|
|
67
|
+
*
|
|
68
|
+
* @param {string} projectDir
|
|
69
|
+
* @param {string} runId
|
|
70
|
+
* @param {{ sample?: number }} [opts]
|
|
71
|
+
* @returns {{ run_id: string, sample_size: number, selected: Array<{ milestone_id: string, title: string, probe_run_count: number, last_probe_run_at: string | null }> }}
|
|
72
|
+
*/
|
|
73
|
+
export function selectSweepSample(projectDir: string, runId: string, { sample }?: {
|
|
74
|
+
sample?: number;
|
|
75
|
+
}): {
|
|
76
|
+
run_id: string;
|
|
77
|
+
sample_size: number;
|
|
78
|
+
selected: Array<{
|
|
79
|
+
milestone_id: string;
|
|
80
|
+
title: string;
|
|
81
|
+
probe_run_count: number;
|
|
82
|
+
last_probe_run_at: string | null;
|
|
83
|
+
}>;
|
|
84
|
+
};
|
|
85
|
+
//# sourceMappingURL=blind-probe.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blind-probe.d.mts","sourceRoot":"","sources":["../../../src/cli/produce/blind-probe.mjs"],"names":[],"mappings":"AA4CA,8DAA8D;AAC9D,uFAEC;AAED,8EAA8E;AAC9E,iFAQC;AAkBD;;;;;;;;;;;;;;;GAeG;AACH,2CARW,MAAM,SACN,MAAM,eACN,MAAM,gDACN;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAA;CAAE,QACrE,IAAI,GACF;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,cAAc,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,GAClF;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAgEnC;AAED;;;;;;;;;;;GAWG;AACH,2CALW,MAAM,wDACN;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC1F;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAC1E;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAqBnC;AAED;;;;;;;;;;;GAWG;AACH,8CALW,MAAM,SACN,MAAM,eACN;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GACjB;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,KAAK,CAAC;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAC;QAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAA;CAAE,CA6CxK"}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @internal
|
|
3
|
+
* produce/blind-probe.mjs — the held-out cross-family blind-probe set (M2, AC4-6).
|
|
4
|
+
*
|
|
5
|
+
* A fixed 10–20 behavioral probe set the implementer/Showrunner NEVER sees
|
|
6
|
+
* (probe-blindness, US-4 / ID-06), authored + run by a provider family DISJOINT
|
|
7
|
+
* from the implementer's, re-run on a rotating sample of already-done milestones
|
|
8
|
+
* against HEAD (US-6).
|
|
9
|
+
*
|
|
10
|
+
* The probe SET is a frozen immutable artifact at
|
|
11
|
+
* `.aperant/produce/<run-id>/probes/<milestone>.json`, written ONCE via
|
|
12
|
+
* `openSync(path, 'wx')` exclusive-create — a second freeze throws EEXIST and
|
|
13
|
+
* returns the byte-identical stored set (mirrors setpoint.mjs::freezeSetpoint).
|
|
14
|
+
* Its CONTENT never enters the event log or the roadmap projection the
|
|
15
|
+
* Showrunner re-reads each tick (structural probe-blindness, ID-M2-03): the
|
|
16
|
+
* `produce.probe.frozen` event carries ONLY `{probe_set_hash, author_family}`
|
|
17
|
+
* and `produce.probe.run` carries ONLY `{result, probe_family, head_sha}`.
|
|
18
|
+
*/
|
|
19
|
+
import { createHash } from 'node:crypto';
|
|
20
|
+
import { closeSync, existsSync, fsyncSync, mkdirSync, openSync, readFileSync, writeSync, } from 'node:fs';
|
|
21
|
+
import { join } from 'node:path';
|
|
22
|
+
import { appendProduceEvent, readImplementerFamily, readProduceRunEventsMatching, } from './events.mjs';
|
|
23
|
+
import { normalizeFamily } from './probe-family.mjs';
|
|
24
|
+
import { projectRoadmap } from './projection.mjs';
|
|
25
|
+
import { resolveRunDir } from './run-id.mjs';
|
|
26
|
+
/** sha256 of the canonical JSON of the probe content (the immutable hash stamp). */
|
|
27
|
+
function computeProbeSetHash(content) {
|
|
28
|
+
return createHash('sha256').update(JSON.stringify(content)).digest('hex');
|
|
29
|
+
}
|
|
30
|
+
/** The probes/<milestone>.json path for a run + milestone. */
|
|
31
|
+
export function probeSetPathFor(projectDir, runId, milestoneId) {
|
|
32
|
+
return join(resolveRunDir(projectDir, runId), 'probes', `${milestoneId}.json`);
|
|
33
|
+
}
|
|
34
|
+
/** Read + parse a frozen probe set. Returns null when absent or malformed. */
|
|
35
|
+
export function readProbeSet(projectDir, runId, milestoneId) {
|
|
36
|
+
const p = probeSetPathFor(projectDir, runId, milestoneId);
|
|
37
|
+
if (!existsSync(p))
|
|
38
|
+
return null;
|
|
39
|
+
try {
|
|
40
|
+
return JSON.parse(readFileSync(p, 'utf-8'));
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Exclusive-create write of the frozen probe set on the FINAL path (NOT
|
|
48
|
+
* tmp+rename), so a SECOND write throws EEXIST — the set is immutable.
|
|
49
|
+
*/
|
|
50
|
+
function writeProbeSetExclusive(probePath, probeSet) {
|
|
51
|
+
mkdirSync(join(probePath, '..'), { recursive: true });
|
|
52
|
+
const payload = `${JSON.stringify(probeSet, null, 2)}\n`;
|
|
53
|
+
const fd = openSync(probePath, 'wx'); // throws EEXIST when already frozen
|
|
54
|
+
try {
|
|
55
|
+
writeSync(fd, payload, 0, 'utf-8');
|
|
56
|
+
fsyncSync(fd);
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
closeSync(fd);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Freeze a blind-probe set for a milestone, idempotently. REFUSES fail-closed
|
|
64
|
+
* when the author family equals the implementer family (a held-out probe an
|
|
65
|
+
* implementer authored is not held out — ID-06) or when no implementer family
|
|
66
|
+
* is recorded (ID-M2-02). On a FRESH freeze appends `produce.probe.frozen`
|
|
67
|
+
* carrying ONLY the hash + author family (never the content). A second freeze
|
|
68
|
+
* returns the byte-identical stored set (`reused: true`) and never re-logs.
|
|
69
|
+
*
|
|
70
|
+
* @param {string} projectDir
|
|
71
|
+
* @param {string} runId
|
|
72
|
+
* @param {string} milestoneId
|
|
73
|
+
* @param {{ content: unknown, authorFamily: string, implementerFamily: string }} args
|
|
74
|
+
* @param {Date} [now]
|
|
75
|
+
* @returns {{ ok: true, reused: boolean, probe_set_hash: string, author_family: string }
|
|
76
|
+
* | { ok: false, reason: string }}
|
|
77
|
+
*/
|
|
78
|
+
export function freezeProbeSet(projectDir, runId, milestoneId, { content, authorFamily, implementerFamily }, now = new Date()) {
|
|
79
|
+
if (!authorFamily)
|
|
80
|
+
return { ok: false, reason: 'no_author_family' };
|
|
81
|
+
if (!implementerFamily)
|
|
82
|
+
return { ok: false, reason: 'no_implementer_family' };
|
|
83
|
+
// Cross-family enforcement (normalized so claude-code === claude).
|
|
84
|
+
if (normalizeFamily(authorFamily) === normalizeFamily(implementerFamily))
|
|
85
|
+
return { ok: false, reason: 'same_family_author' };
|
|
86
|
+
const probePath = probeSetPathFor(projectDir, runId, milestoneId);
|
|
87
|
+
const existing = readProbeSet(projectDir, runId, milestoneId);
|
|
88
|
+
if (existing)
|
|
89
|
+
return {
|
|
90
|
+
ok: true,
|
|
91
|
+
reused: true,
|
|
92
|
+
probe_set_hash: existing.probe_set_hash,
|
|
93
|
+
author_family: existing.author_family,
|
|
94
|
+
};
|
|
95
|
+
const probeSetHash = computeProbeSetHash(content ?? null);
|
|
96
|
+
const probeSet = {
|
|
97
|
+
run_id: runId,
|
|
98
|
+
milestone_id: milestoneId,
|
|
99
|
+
author_family: authorFamily,
|
|
100
|
+
frozen_at: now.toISOString(),
|
|
101
|
+
probe_set_hash: probeSetHash,
|
|
102
|
+
// The probe CONTENT lives in the frozen file (blind to the projection) —
|
|
103
|
+
// it NEVER enters the event log.
|
|
104
|
+
probes: content ?? null,
|
|
105
|
+
};
|
|
106
|
+
try {
|
|
107
|
+
writeProbeSetExclusive(probePath, probeSet);
|
|
108
|
+
}
|
|
109
|
+
catch (e) {
|
|
110
|
+
// Lost a concurrent race — the winner's file is authoritative; re-read it
|
|
111
|
+
// byte-identically rather than overwriting (mirrors freezeSetpoint).
|
|
112
|
+
if (e && e.code === 'EEXIST') {
|
|
113
|
+
const winner = readProbeSet(projectDir, runId, milestoneId);
|
|
114
|
+
if (winner)
|
|
115
|
+
return {
|
|
116
|
+
ok: true,
|
|
117
|
+
reused: true,
|
|
118
|
+
probe_set_hash: winner.probe_set_hash,
|
|
119
|
+
author_family: winner.author_family,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
throw e;
|
|
123
|
+
}
|
|
124
|
+
// Announce by hash + author family ONLY — never the content (ID-M2-03).
|
|
125
|
+
appendProduceEvent(projectDir, 'produce.probe.frozen', {
|
|
126
|
+
run_id: runId,
|
|
127
|
+
milestone_id: milestoneId,
|
|
128
|
+
probe_set_hash: probeSetHash,
|
|
129
|
+
author_family: authorFamily,
|
|
130
|
+
});
|
|
131
|
+
return { ok: true, reused: false, probe_set_hash: probeSetHash, author_family: authorFamily };
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Record a blind-probe RUN result. REFUSES fail-closed when the probe family
|
|
135
|
+
* equals the implementer family (a probe run BY the implementer family is not
|
|
136
|
+
* cross-family — ID-08) or when no implementer family is recorded. On
|
|
137
|
+
* acceptance appends `produce.probe.run {run_id, milestone_id, result,
|
|
138
|
+
* probe_family, head_sha}` — result/family/head_sha only, never content.
|
|
139
|
+
*
|
|
140
|
+
* @param {string} projectDir
|
|
141
|
+
* @param {{ runId: string, milestoneId: string, result: string, probeFamily: string, headSha: string }} args
|
|
142
|
+
* @returns {{ ok: true, result: string, probe_family: string, head_sha: string }
|
|
143
|
+
* | { ok: false, reason: string }}
|
|
144
|
+
*/
|
|
145
|
+
export function recordProbeRun(projectDir, { runId, milestoneId, result, probeFamily, headSha }) {
|
|
146
|
+
if (result !== 'pass' && result !== 'fail')
|
|
147
|
+
return { ok: false, reason: 'invalid_result' };
|
|
148
|
+
if (!probeFamily)
|
|
149
|
+
return { ok: false, reason: 'no_probe_family' };
|
|
150
|
+
if (!headSha)
|
|
151
|
+
return { ok: false, reason: 'no_head_sha' };
|
|
152
|
+
const implementerFamily = readImplementerFamily(projectDir, runId, milestoneId);
|
|
153
|
+
if (!implementerFamily)
|
|
154
|
+
return { ok: false, reason: 'no_recorded_implementer' };
|
|
155
|
+
if (normalizeFamily(probeFamily) === normalizeFamily(implementerFamily))
|
|
156
|
+
return { ok: false, reason: 'same_family_probe' };
|
|
157
|
+
appendProduceEvent(projectDir, 'produce.probe.run', {
|
|
158
|
+
run_id: runId,
|
|
159
|
+
milestone_id: milestoneId,
|
|
160
|
+
result,
|
|
161
|
+
probe_family: probeFamily,
|
|
162
|
+
head_sha: headSha,
|
|
163
|
+
});
|
|
164
|
+
return { ok: true, result, probe_family: probeFamily, head_sha: headSha };
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Select a DETERMINISTIC rotating sample of already-`done` milestones for blind
|
|
168
|
+
* re-probing against HEAD (US-6). Rotates by fewest prior probe runs first,
|
|
169
|
+
* then oldest last-probe-run first (a never-probed done milestone sorts first),
|
|
170
|
+
* then first-seen roadmap order — so two folds of the same log select the same
|
|
171
|
+
* sample.
|
|
172
|
+
*
|
|
173
|
+
* @param {string} projectDir
|
|
174
|
+
* @param {string} runId
|
|
175
|
+
* @param {{ sample?: number }} [opts]
|
|
176
|
+
* @returns {{ run_id: string, sample_size: number, selected: Array<{ milestone_id: string, title: string, probe_run_count: number, last_probe_run_at: string | null }> }}
|
|
177
|
+
*/
|
|
178
|
+
export function selectSweepSample(projectDir, runId, { sample = 1 } = {}) {
|
|
179
|
+
const roadmap = projectRoadmap(projectDir, runId);
|
|
180
|
+
const done = roadmap.milestones.filter((m) => m.status === 'done');
|
|
181
|
+
const runEvents = readProduceRunEventsMatching(projectDir, runId, (op) => op === 'produce.probe.run');
|
|
182
|
+
const stats = new Map();
|
|
183
|
+
for (const e of runEvents) {
|
|
184
|
+
const id = e.data && typeof e.data.milestone_id === 'string' ? e.data.milestone_id : null;
|
|
185
|
+
if (!id)
|
|
186
|
+
continue;
|
|
187
|
+
const s = stats.get(id) || { count: 0, last: null };
|
|
188
|
+
s.count += 1;
|
|
189
|
+
if (typeof e.t === 'string' && (s.last === null || e.t > s.last))
|
|
190
|
+
s.last = e.t;
|
|
191
|
+
stats.set(id, s);
|
|
192
|
+
}
|
|
193
|
+
const withOrder = done.map((m, idx) => {
|
|
194
|
+
const s = stats.get(m.id) || { count: 0, last: null };
|
|
195
|
+
return { milestone: m, order: idx, count: s.count, last: s.last };
|
|
196
|
+
});
|
|
197
|
+
withOrder.sort((a, b) => {
|
|
198
|
+
if (a.count !== b.count)
|
|
199
|
+
return a.count - b.count; // fewest probe runs first
|
|
200
|
+
// oldest last-probe-run first — a never-probed done milestone (null) sorts
|
|
201
|
+
// ahead of any dated one.
|
|
202
|
+
const al = a.last ?? '';
|
|
203
|
+
const bl = b.last ?? '';
|
|
204
|
+
if (al !== bl)
|
|
205
|
+
return al < bl ? -1 : 1;
|
|
206
|
+
return a.order - b.order; // first-seen roadmap order (stable tiebreak)
|
|
207
|
+
});
|
|
208
|
+
const n = Number.isFinite(sample) && sample > 0 ? Math.floor(sample) : 1;
|
|
209
|
+
const selected = withOrder.slice(0, n).map((w) => ({
|
|
210
|
+
milestone_id: w.milestone.id,
|
|
211
|
+
title: w.milestone.title,
|
|
212
|
+
probe_run_count: w.count,
|
|
213
|
+
last_probe_run_at: w.last,
|
|
214
|
+
}));
|
|
215
|
+
return { run_id: runId, sample_size: selected.length, selected };
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=blind-probe.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blind-probe.mjs","sourceRoot":"","sources":["../../../src/cli/produce/blind-probe.mjs"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validate a Claim Envelope by dispatching on `envelope.profile` through the
|
|
3
|
+
* REGISTRY (never a hardcoded profile branch — ID-M6-02). An unknown/absent
|
|
4
|
+
* profile fails closed (`{ ok:false, reason:'unknown_profile' }`). Never throws.
|
|
5
|
+
*
|
|
6
|
+
* @param {Record<string, unknown>} envelope
|
|
7
|
+
* @param {{ profiles?: Record<string, { validate: (env: Record<string, unknown>) => { ok: boolean, reason?: string } }> }} [opts]
|
|
8
|
+
* @returns {{ ok: true } | { ok: false, reason: string }}
|
|
9
|
+
*/
|
|
10
|
+
export function validateClaimEnvelope(envelope: Record<string, unknown>, { profiles }?: {
|
|
11
|
+
profiles?: Record<string, {
|
|
12
|
+
validate: (env: Record<string, unknown>) => {
|
|
13
|
+
ok: boolean;
|
|
14
|
+
reason?: string;
|
|
15
|
+
};
|
|
16
|
+
}>;
|
|
17
|
+
}): {
|
|
18
|
+
ok: true;
|
|
19
|
+
} | {
|
|
20
|
+
ok: false;
|
|
21
|
+
reason: string;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Mint a claim id: `<slug-of-text>-<rand>`. Reuses `slugFromOutcome` + a short
|
|
25
|
+
* random suffix (mirrors ledger.mjs::mintCriterionId) so two claims minted from
|
|
26
|
+
* the same text never collide. Falls back to the profile when text is empty.
|
|
27
|
+
*
|
|
28
|
+
* @param {string} profile
|
|
29
|
+
* @param {string} text
|
|
30
|
+
* @returns {string}
|
|
31
|
+
*/
|
|
32
|
+
export function mintClaimId(profile: string, text: string): string;
|
|
33
|
+
/** The claims/<claim-id>.json path for a run + claim. */
|
|
34
|
+
export function claimPathFor(projectDir: any, runId: any, claimId: any): string;
|
|
35
|
+
/** Read + parse a frozen claim record. Returns null when absent or malformed. */
|
|
36
|
+
export function readClaim(projectDir: any, runId: any, claimId: any): any;
|
|
37
|
+
/**
|
|
38
|
+
* Freeze a Claim Envelope, idempotently. VALIDATES first (refuses to freeze an
|
|
39
|
+
* invalid envelope — fail-closed), computes `content_hash = sha256(envelope)`,
|
|
40
|
+
* writes `claims/<claim-id>.json` exclusive-create, and on a FRESH freeze appends
|
|
41
|
+
* `produce.claim.declared {run_id, profile, claim_id, content_hash}` (content_hash
|
|
42
|
+
* only — the full envelope lives in the frozen file, ID-M6-07). A second freeze
|
|
43
|
+
* of the same claim id returns the byte-identical stored record (`reused: true`)
|
|
44
|
+
* and never re-logs. The resolved `profile` (explicit arg or `envelope.profile`)
|
|
45
|
+
* is authoritative for validation dispatch + the stored/logged profile.
|
|
46
|
+
*
|
|
47
|
+
* @param {string} projectDir
|
|
48
|
+
* @param {string} runId
|
|
49
|
+
* @param {{ profile?: string, envelope: Record<string, unknown>, claimId?: string }} args
|
|
50
|
+
* @param {{ profiles?: object, now?: Date }} [opts]
|
|
51
|
+
* @returns {{ ok: true, reused: boolean, claim_id: string, profile: string | null, content_hash: string }
|
|
52
|
+
* | { ok: false, reason: string }}
|
|
53
|
+
*/
|
|
54
|
+
export function freezeClaim(projectDir: string, runId: string, { profile, envelope, claimId }?: {
|
|
55
|
+
profile?: string;
|
|
56
|
+
envelope: Record<string, unknown>;
|
|
57
|
+
claimId?: string;
|
|
58
|
+
}, { profiles, now }?: {
|
|
59
|
+
profiles?: object;
|
|
60
|
+
now?: Date;
|
|
61
|
+
}): {
|
|
62
|
+
ok: true;
|
|
63
|
+
reused: boolean;
|
|
64
|
+
claim_id: string;
|
|
65
|
+
profile: string | null;
|
|
66
|
+
content_hash: string;
|
|
67
|
+
} | {
|
|
68
|
+
ok: false;
|
|
69
|
+
reason: string;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Fold the run's claim ledger from the append-only log — a SEPARATE fold parallel
|
|
73
|
+
* to `ledger.mjs::projectLedger` / `saga.mjs::projectSaga` (the roadmap projection
|
|
74
|
+
* still folds `produce.roadmap.*` ONLY, so claim ops never enter the roadmap the
|
|
75
|
+
* Showrunner re-reads). A `produce.claim.declared` seeds an ACTIVE claim (in
|
|
76
|
+
* first-seen order); a `produce.claim.expired` advances it to `expired`;
|
|
77
|
+
* `produce.claim.consumed` is a forensic-only event that does NOT change status.
|
|
78
|
+
* Deterministic — two folds of the same log yield the identical ledger.
|
|
79
|
+
*
|
|
80
|
+
* @param {string} projectDir
|
|
81
|
+
* @param {string} runId
|
|
82
|
+
* @returns {{
|
|
83
|
+
* run_id: string,
|
|
84
|
+
* claims: Array<{ claim_id: string, profile: string | null, content_hash: string | null, status: 'active' | 'expired' }>,
|
|
85
|
+
* active_count: number,
|
|
86
|
+
* expired_count: number,
|
|
87
|
+
* updated_at: string | null,
|
|
88
|
+
* }}
|
|
89
|
+
*/
|
|
90
|
+
export function projectClaims(projectDir: string, runId: string): {
|
|
91
|
+
run_id: string;
|
|
92
|
+
claims: Array<{
|
|
93
|
+
claim_id: string;
|
|
94
|
+
profile: string | null;
|
|
95
|
+
content_hash: string | null;
|
|
96
|
+
status: "active" | "expired";
|
|
97
|
+
}>;
|
|
98
|
+
active_count: number;
|
|
99
|
+
expired_count: number;
|
|
100
|
+
updated_at: string | null;
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* Decide whether a claim may be consumed against a ctx (ID-M6-04, anti-corrosion).
|
|
104
|
+
* DETERMINISTIC (no LLM). SKIPS with a reason when: the claim is time-expired
|
|
105
|
+
* (`now() > expiry.expires_at` → `expired`); the claim's `revalidate_against_head`
|
|
106
|
+
* check no longer matches HEAD (`headCheck(check) === false` → `head_invalidated`);
|
|
107
|
+
* or the preconditions don't match ctx (`precondition_unmatched`). Otherwise
|
|
108
|
+
* `{ consume: true }`. `now` + `headCheck` are INJECTED (default now = new Date,
|
|
109
|
+
* default headCheck = the working-tree path-exists/grep).
|
|
110
|
+
*
|
|
111
|
+
* @param {Record<string, unknown>} claim — the claim ENVELOPE (carries expiry + preconditions).
|
|
112
|
+
* @param {Record<string, unknown>} [ctx]
|
|
113
|
+
* @param {{ now?: () => Date, headCheck?: (check: unknown) => boolean }} [deps]
|
|
114
|
+
* @returns {{ consume: true } | { consume: false, reason: string }}
|
|
115
|
+
*/
|
|
116
|
+
export function evaluateClaimForConsumption(claim: Record<string, unknown>, ctx?: Record<string, unknown>, deps?: {
|
|
117
|
+
now?: () => Date;
|
|
118
|
+
headCheck?: (check: unknown) => boolean;
|
|
119
|
+
}): {
|
|
120
|
+
consume: true;
|
|
121
|
+
} | {
|
|
122
|
+
consume: false;
|
|
123
|
+
reason: string;
|
|
124
|
+
};
|
|
125
|
+
/**
|
|
126
|
+
* Consume the run's ACTIVE claims against a ctx (ID-M6-06 — THE M6 invariant).
|
|
127
|
+
* For each active claim, evaluate it; a consumable claim emits ONE bounded delta
|
|
128
|
+
* `{ claim_id, profile, targets: [{ kind, requirement, ref? }] }` where every
|
|
129
|
+
* `targets[].kind ∈ CLAIM_TARGET_KINDS` and `requirement` is derived FROM
|
|
130
|
+
* `resolution_verifier` — a projection DOWN. The output MUST NOT carry the claim's
|
|
131
|
+
* `provenance` / `negative_evidence` / `preconditions` / body (never a context
|
|
132
|
+
* paste). Skipped claims (expired / head_invalidated / precondition_unmatched /
|
|
133
|
+
* unreadable) surface under `skipped[]` with a reason. PURE — appends no event
|
|
134
|
+
* (the CLI records `produce.claim.consumed` per target for the forensic trail).
|
|
135
|
+
*
|
|
136
|
+
* @param {string} projectDir
|
|
137
|
+
* @param {string} runId
|
|
138
|
+
* @param {Record<string, unknown>} [ctx]
|
|
139
|
+
* @param {{ now?: () => Date, headCheck?: (check: unknown) => boolean }} [deps]
|
|
140
|
+
* @returns {{
|
|
141
|
+
* consumed: Array<{ claim_id: string, profile: string | null, targets: Array<{ kind: string, requirement: string, ref?: string }> }>,
|
|
142
|
+
* skipped: Array<{ claim_id: string, reason: string }>,
|
|
143
|
+
* }}
|
|
144
|
+
*/
|
|
145
|
+
export function consumeClaims(projectDir: string, runId: string, ctx?: Record<string, unknown>, deps?: {
|
|
146
|
+
now?: () => Date;
|
|
147
|
+
headCheck?: (check: unknown) => boolean;
|
|
148
|
+
}): {
|
|
149
|
+
consumed: Array<{
|
|
150
|
+
claim_id: string;
|
|
151
|
+
profile: string | null;
|
|
152
|
+
targets: Array<{
|
|
153
|
+
kind: string;
|
|
154
|
+
requirement: string;
|
|
155
|
+
ref?: string;
|
|
156
|
+
}>;
|
|
157
|
+
}>;
|
|
158
|
+
skipped: Array<{
|
|
159
|
+
claim_id: string;
|
|
160
|
+
reason: string;
|
|
161
|
+
}>;
|
|
162
|
+
};
|
|
163
|
+
export namespace CLAIM_PROFILES {
|
|
164
|
+
namespace lesson {
|
|
165
|
+
export let requiredFields: string[];
|
|
166
|
+
export { validateLessonEnvelope as validate };
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
/** The closed set of consumption-delta target kinds (mirrors ALLOWED_CLAIM_TARGET_KINDS). */
|
|
170
|
+
export const CLAIM_TARGET_KINDS: string[];
|
|
171
|
+
/**
|
|
172
|
+
* The `lesson` profile validator (ID-M6-03). REQUIRES all 6 AC15 fields and
|
|
173
|
+
* REJECTS fail-closed (never throws): missing provenance; empty preconditions
|
|
174
|
+
* (unconditional rule — bounded-critic clamp); global/unbounded scope
|
|
175
|
+
* (anti-windup); missing expiry (anti-corrosion); missing negative_evidence
|
|
176
|
+
* field; empty resolution_verifier. Returns `{ ok:false, reason }`.
|
|
177
|
+
*
|
|
178
|
+
* @param {Record<string, unknown>} env
|
|
179
|
+
* @returns {{ ok: true } | { ok: false, reason: string }}
|
|
180
|
+
*/
|
|
181
|
+
declare function validateLessonEnvelope(env: Record<string, unknown>): {
|
|
182
|
+
ok: true;
|
|
183
|
+
} | {
|
|
184
|
+
ok: false;
|
|
185
|
+
reason: string;
|
|
186
|
+
};
|
|
187
|
+
export {};
|
|
188
|
+
//# sourceMappingURL=claim.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claim.d.mts","sourceRoot":"","sources":["../../../src/cli/produce/claim.mjs"],"names":[],"mappings":"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"}
|