@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
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @internal
|
|
3
|
+
* produce/verification-ttl.mjs — verification-TTL: a rotating sample of OLD done
|
|
4
|
+
* milestones re-verified against HEAD each tick, regressions flagged +
|
|
5
|
+
* compensated (M4, ID-M4-03 / AC13).
|
|
6
|
+
*
|
|
7
|
+
* Verification is not permanent — a milestone marked `done` at HEAD-sha `A` can
|
|
8
|
+
* silently regress as HEAD advances to `B` (a later milestone's change breaks an
|
|
9
|
+
* earlier one). This module gives verification a TTL:
|
|
10
|
+
*
|
|
11
|
+
* - `selectTtlReverifySample` REUSES M2's `selectSweepSample` for the rotating
|
|
12
|
+
* done-milestone candidates (do NOT invent a parallel rotation) and annotates
|
|
13
|
+
* staleness against the supplied HEAD sha — a done milestone is STALE when its
|
|
14
|
+
* last recorded `produce.ttl.reverified`/`produce.probe.run` head_sha ≠ the
|
|
15
|
+
* current HEAD (or it has never been re-verified since done); a milestone last
|
|
16
|
+
* re-verified against the current HEAD is EXCLUDED as FRESH.
|
|
17
|
+
* - `recordTtlReverify` REUSES the M2 cross-family guard (refuses a same-family
|
|
18
|
+
* re-verify), appends `produce.ttl.reverified`, and on `fail` ALSO appends
|
|
19
|
+
* `produce.ttl.regression_detected` AND fires the FORWARD compensator via
|
|
20
|
+
* saga.mjs::compensatePhase({phase:'verify'}) — a revert-branch + reopen +
|
|
21
|
+
* re-plan, NEVER a merged-PR rollback (ID-M4-03).
|
|
22
|
+
*
|
|
23
|
+
* `ttl.reverified` is a DISTINCT op from `probe.run` (a scheduled post-`done` TTL
|
|
24
|
+
* re-check vs a first-time done-gate probe) so the forensic trail stays clean —
|
|
25
|
+
* only the ROTATION and the CROSS-FAMILY GUARD are reused. This module records +
|
|
26
|
+
* computes; the actual re-verify RUN + the revert-ship/reopen/re-plan EXECUTION
|
|
27
|
+
* is the OOS dispatch layer.
|
|
28
|
+
*/
|
|
29
|
+
import { selectSweepSample } from './blind-probe.mjs';
|
|
30
|
+
import { appendProduceEvent, readImplementerFamily, readProduceRunEventsMatching, } from './events.mjs';
|
|
31
|
+
import { normalizeFamily } from './probe-family.mjs';
|
|
32
|
+
import { projectRoadmap } from './projection.mjs';
|
|
33
|
+
import { compensatePhase } from './saga.mjs';
|
|
34
|
+
/**
|
|
35
|
+
* Build the per-milestone latest-recorded head_sha map from the
|
|
36
|
+
* `produce.ttl.reverified` + `produce.probe.run` events (both carry `head_sha`).
|
|
37
|
+
* Chronological fold — the last recorded run for a milestone wins.
|
|
38
|
+
*
|
|
39
|
+
* @param {string} projectDir
|
|
40
|
+
* @param {string} runId
|
|
41
|
+
* @returns {Map<string, { head_sha: string, at: string | null }>}
|
|
42
|
+
*/
|
|
43
|
+
function latestReverifyByMilestone(projectDir, runId) {
|
|
44
|
+
const events = readProduceRunEventsMatching(projectDir, runId, (op) => op === 'produce.ttl.reverified' || op === 'produce.probe.run');
|
|
45
|
+
const map = new Map();
|
|
46
|
+
for (const e of events) {
|
|
47
|
+
const d = e.data || {};
|
|
48
|
+
const id = typeof d.milestone_id === 'string' ? d.milestone_id : null;
|
|
49
|
+
const sha = typeof d.head_sha === 'string' ? d.head_sha : null;
|
|
50
|
+
if (!id || !sha)
|
|
51
|
+
continue;
|
|
52
|
+
map.set(id, { head_sha: sha, at: typeof e.t === 'string' ? e.t : null });
|
|
53
|
+
}
|
|
54
|
+
return map;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Select a DETERMINISTIC rotating sample of already-`done` milestones STALE
|
|
58
|
+
* against HEAD (ID-M4-03 / AC7). REUSES `selectSweepSample` for the rotation
|
|
59
|
+
* order (fewest/oldest last-probe-run first), then annotates each candidate with
|
|
60
|
+
* staleness against `headSha` and FILTERS OUT the FRESH ones (last re-verified
|
|
61
|
+
* against the current HEAD). Returns the first `sample` STALE candidates. An
|
|
62
|
+
* absent HEAD sha fails closed (nothing selected).
|
|
63
|
+
*
|
|
64
|
+
* @param {string} projectDir
|
|
65
|
+
* @param {string} runId
|
|
66
|
+
* @param {{ headSha: string, sample?: number }} args
|
|
67
|
+
* @returns {{ run_id: string, head_sha: string | null, sample_size: number,
|
|
68
|
+
* selected: Array<{ milestone_id: string, title: string, last_reverify_head_sha: string | null, last_reverify_at: string | null, stale: boolean }> }}
|
|
69
|
+
*/
|
|
70
|
+
export function selectTtlReverifySample(projectDir, runId, { headSha, sample = 1 } = {}) {
|
|
71
|
+
if (!headSha)
|
|
72
|
+
return { run_id: runId, head_sha: null, sample_size: 0, selected: [] };
|
|
73
|
+
// The FULL rotation-ordered pool of done milestones (reuse selectSweepSample;
|
|
74
|
+
// pass the done count so it returns every done milestone in rotation order).
|
|
75
|
+
const doneCount = projectRoadmap(projectDir, runId).milestones.filter((m) => m.status === 'done').length;
|
|
76
|
+
const pool = selectSweepSample(projectDir, runId, { sample: doneCount || 1 }).selected;
|
|
77
|
+
const latest = latestReverifyByMilestone(projectDir, runId);
|
|
78
|
+
const n = Number.isFinite(sample) && sample > 0 ? Math.floor(sample) : 1;
|
|
79
|
+
const stale = [];
|
|
80
|
+
for (const candidate of pool) {
|
|
81
|
+
const last = latest.get(candidate.milestone_id) || null;
|
|
82
|
+
// STALE when never re-verified since done, or last re-verified against a sha
|
|
83
|
+
// ≠ the current HEAD. FRESH (last re-verify head_sha === HEAD) is excluded.
|
|
84
|
+
const isStale = !last || last.head_sha !== headSha;
|
|
85
|
+
if (!isStale)
|
|
86
|
+
continue;
|
|
87
|
+
stale.push({
|
|
88
|
+
milestone_id: candidate.milestone_id,
|
|
89
|
+
title: candidate.title,
|
|
90
|
+
last_reverify_head_sha: last?.head_sha ?? null,
|
|
91
|
+
last_reverify_at: last?.at ?? null,
|
|
92
|
+
stale: true,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
const selected = stale.slice(0, n);
|
|
96
|
+
return { run_id: runId, head_sha: headSha, sample_size: selected.length, selected };
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Record a scheduled TTL re-verify RUN against HEAD (ID-M4-03). REUSES the M2
|
|
100
|
+
* cross-family guard (refuses a same-family re-verify, or when no implementer
|
|
101
|
+
* family is recorded). Appends `produce.ttl.reverified {run_id, milestone_id,
|
|
102
|
+
* head_sha, result}`; on `result === 'fail'` ALSO appends
|
|
103
|
+
* `produce.ttl.regression_detected` AND fires the FORWARD compensator via
|
|
104
|
+
* saga.mjs::compensatePhase({phase:'verify', reason:'ttl_regression@<sha>'}) — a
|
|
105
|
+
* revert-branch + reopen + re-plan, NEVER a merged-PR rollback. A `pass`
|
|
106
|
+
* refreshes verification against the new HEAD and logs no regression.
|
|
107
|
+
*
|
|
108
|
+
* @param {string} projectDir
|
|
109
|
+
* @param {{ runId: string, milestoneId: string, result: string, probeFamily: string, headSha: string }} args
|
|
110
|
+
* @returns {{ ok: true, result: string, probe_family: string, head_sha: string, regression: boolean, compensator: object | null }
|
|
111
|
+
* | { ok: false, reason: string }}
|
|
112
|
+
*/
|
|
113
|
+
export function recordTtlReverify(projectDir, { runId, milestoneId, result, probeFamily, headSha }) {
|
|
114
|
+
if (result !== 'pass' && result !== 'fail')
|
|
115
|
+
return { ok: false, reason: 'invalid_result' };
|
|
116
|
+
if (!headSha)
|
|
117
|
+
return { ok: false, reason: 'no_head_sha' };
|
|
118
|
+
if (!probeFamily)
|
|
119
|
+
return { ok: false, reason: 'no_probe_family' };
|
|
120
|
+
const implementerFamily = readImplementerFamily(projectDir, runId, milestoneId);
|
|
121
|
+
if (!implementerFamily)
|
|
122
|
+
return { ok: false, reason: 'no_recorded_implementer' };
|
|
123
|
+
// Cross-family enforcement (normalized so claude-code === claude).
|
|
124
|
+
if (normalizeFamily(probeFamily) === normalizeFamily(implementerFamily))
|
|
125
|
+
return { ok: false, reason: 'same_family_reverify' };
|
|
126
|
+
appendProduceEvent(projectDir, 'produce.ttl.reverified', {
|
|
127
|
+
run_id: runId,
|
|
128
|
+
milestone_id: milestoneId,
|
|
129
|
+
head_sha: headSha,
|
|
130
|
+
result,
|
|
131
|
+
});
|
|
132
|
+
let regression = false;
|
|
133
|
+
let compensator = null;
|
|
134
|
+
if (result === 'fail') {
|
|
135
|
+
// The regression flags the milestone AND fires the FORWARD compensator — a
|
|
136
|
+
// revert-branch + reopen + re-plan, never a merged-PR rollback (ID-M4-03).
|
|
137
|
+
appendProduceEvent(projectDir, 'produce.ttl.regression_detected', {
|
|
138
|
+
run_id: runId,
|
|
139
|
+
milestone_id: milestoneId,
|
|
140
|
+
head_sha: headSha,
|
|
141
|
+
});
|
|
142
|
+
const comp = compensatePhase(projectDir, {
|
|
143
|
+
runId,
|
|
144
|
+
milestoneId,
|
|
145
|
+
phase: 'verify',
|
|
146
|
+
reason: `ttl_regression@${headSha}`,
|
|
147
|
+
});
|
|
148
|
+
regression = true;
|
|
149
|
+
compensator = comp.ok ? comp.compensator : null;
|
|
150
|
+
}
|
|
151
|
+
return { ok: true, result, probe_family: probeFamily, head_sha: headSha, regression, compensator };
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Read-only fold of the run's `produce.ttl.regression_detected` events (for saga
|
|
155
|
+
* status / canary context). Chronological order.
|
|
156
|
+
*
|
|
157
|
+
* @param {string} projectDir
|
|
158
|
+
* @param {string} runId
|
|
159
|
+
* @returns {Array<{ milestone_id: string | null, head_sha: string | null, t: string | null }>}
|
|
160
|
+
*/
|
|
161
|
+
export function listRegressions(projectDir, runId) {
|
|
162
|
+
const events = readProduceRunEventsMatching(projectDir, runId, (op) => op === 'produce.ttl.regression_detected');
|
|
163
|
+
return events.map((e) => ({
|
|
164
|
+
milestone_id: e.data && typeof e.data.milestone_id === 'string' ? e.data.milestone_id : null,
|
|
165
|
+
head_sha: e.data && typeof e.data.head_sha === 'string' ? e.data.head_sha : null,
|
|
166
|
+
t: typeof e.t === 'string' ? e.t : null,
|
|
167
|
+
}));
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=verification-ttl.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verification-ttl.mjs","sourceRoot":"","sources":["../../../src/cli/produce/verification-ttl.mjs"],"names":[],"mappings":"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"}
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
* should grow a `Release note: …` line OR ship should block.
|
|
7
7
|
*
|
|
8
8
|
* This module is intentionally pure — the apt-ship SKILL.md body shells
|
|
9
|
-
* `apt-tools features-
|
|
10
|
-
* envelope here. Keeping the decision pure makes TD-4 trivial: fixture in,
|
|
9
|
+
* `apt-tools features-reconcile . --draft --dry-run --base "$base"` and feeds
|
|
10
|
+
* the envelope here. Keeping the decision pure makes TD-4 trivial: fixture in,
|
|
11
11
|
* decision out, no I/O.
|
|
12
12
|
*/
|
|
13
13
|
import { buildPersonaTierMap, classifyFragment } from './persona-filter.mjs';
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Build a flat per-scope roadmap snapshot for the
|
|
2
|
+
* Build a flat per-scope roadmap snapshot for the Showrunner.
|
|
3
3
|
*
|
|
4
4
|
* @param {string} projectRoot
|
|
5
5
|
* @returns {{ scopes: Array<{ scope: string, roadmap: unknown }> }}
|
|
6
6
|
*/
|
|
7
|
-
export function
|
|
7
|
+
export function buildShowrunnerRoadmapView(projectRoot: string): {
|
|
8
8
|
scopes: Array<{
|
|
9
9
|
scope: string;
|
|
10
10
|
roadmap: unknown;
|
|
11
11
|
}>;
|
|
12
12
|
};
|
|
13
|
-
//# sourceMappingURL=
|
|
13
|
+
//# sourceMappingURL=showrunner-view.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"showrunner-view.d.mts","sourceRoot":"","sources":["../../../src/cli/roadmap/showrunner-view.mjs"],"names":[],"mappings":"AAgBA;;;;;GAKG;AACH,wDAHW,MAAM,GACJ;IAAE,MAAM,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAA;CAAE,CAUlE"}
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* showrunner-view.mjs — read-only roadmap surface for the Aperant
|
|
3
|
+
* Showrunner's `getRoadmap` tool.
|
|
4
4
|
*
|
|
5
|
-
* Wraps `loadRoadmapForScope` + `listRoadmapScopes` so the
|
|
5
|
+
* Wraps `loadRoadmapForScope` + `listRoadmapScopes` so the Showrunner sees
|
|
6
6
|
* the same overlay-aware view every framework command sees. Direct reads
|
|
7
7
|
* of `.aperant/roadmap/*\/phases/*.json` or `milestones.json` would miss
|
|
8
8
|
* the dual-write overlay (seed_id from legacy blob, etc.) — Codex
|
|
9
9
|
* roundtable correction #3.
|
|
10
10
|
*
|
|
11
|
-
* Step 5 of
|
|
11
|
+
* Step 5 of Showrunner v2 ship order.
|
|
12
12
|
*/
|
|
13
13
|
import { loadRoadmapForScope } from './io.mjs';
|
|
14
14
|
import { listRoadmapScopes } from './paths.mjs';
|
|
15
15
|
/**
|
|
16
|
-
* Build a flat per-scope roadmap snapshot for the
|
|
16
|
+
* Build a flat per-scope roadmap snapshot for the Showrunner.
|
|
17
17
|
*
|
|
18
18
|
* @param {string} projectRoot
|
|
19
19
|
* @returns {{ scopes: Array<{ scope: string, roadmap: unknown }> }}
|
|
20
20
|
*/
|
|
21
|
-
export function
|
|
21
|
+
export function buildShowrunnerRoadmapView(projectRoot) {
|
|
22
22
|
const scopes = listRoadmapScopes(projectRoot);
|
|
23
23
|
const out = [];
|
|
24
24
|
for (const scope of scopes) {
|
|
@@ -28,4 +28,4 @@ export function buildConductorRoadmapView(projectRoot) {
|
|
|
28
28
|
}
|
|
29
29
|
return { scopes: out };
|
|
30
30
|
}
|
|
31
|
-
//# sourceMappingURL=
|
|
31
|
+
//# sourceMappingURL=showrunner-view.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"showrunner-view.mjs","sourceRoot":"","sources":["../../../src/cli/roadmap/showrunner-view.mjs"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAE/C;;;;;GAKG;AACH,MAAM,UAAU,0BAA0B,CAAC,WAAW;IACrD,MAAM,MAAM,GAAG,iBAAiB,CAAC,WAAW,CAAC,CAAA;IAC7C,MAAM,GAAG,GAAG,EAAE,CAAA;IACd,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAG,mBAAmB,CAAC,WAAW,EAAE,KAAK,CAAC,CAAA;QACvD,IAAI,OAAO,KAAK,IAAI;YAAE,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAA;IACnD,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,CAAA;AACvB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gallery.d.mts","sourceRoot":"","sources":["../../../src/cli/variant/gallery.mjs"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"gallery.d.mts","sourceRoot":"","sources":["../../../src/cli/variant/gallery.mjs"],"names":[],"mappings":"AAkDA;;;;;GAKG;AACH,qCAHW,YAAY,GACV,MAAM,CAkFlB;AAID;;;;;;;;;GASG;AACH,uDAJW,MAAM,EAAE,kBACR,MAAM,CAAC,MAAM,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAAC,GAClE;IAAE,QAAQ,EAAE,cAAc,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAyB7D;6BArJY;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE;2BAC1E;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,cAAc,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE"}
|
|
@@ -12,6 +12,10 @@
|
|
|
12
12
|
* no privilege for that). Picking happens by running a terminal
|
|
13
13
|
* command — the gallery's job is to make the letter obvious and the
|
|
14
14
|
* command copy-pasteable.
|
|
15
|
+
* - Each card links to its variant file via a plain relative anchor
|
|
16
|
+
* with target="_blank", so the user can open any variant full-size
|
|
17
|
+
* in a new tab straight from the gallery (relative hrefs resolve
|
|
18
|
+
* against the gallery's own file:// URL — no server needed).
|
|
15
19
|
* - Responsive grid: 1 column on narrow, 2 on medium, N on wide.
|
|
16
20
|
* - Each variant iframe is rendered at full device-width-feel, not a
|
|
17
21
|
* thumbnail, so the user can actually read the content.
|
|
@@ -74,11 +78,11 @@ export function renderGallery(input) {
|
|
|
74
78
|
` <div class="truncate text-xs text-slate-400">${description}</div>`,
|
|
75
79
|
' </div>',
|
|
76
80
|
' </div>',
|
|
77
|
-
` <
|
|
81
|
+
` <a href="${filename}" target="_blank" rel="noopener" title="Open variant ${letter} in a new tab" class="shrink-0 rounded bg-slate-800 px-2 py-1 text-xs text-slate-300 hover:bg-slate-700 hover:text-slate-100"><code>${filename}</code> ↗</a>`,
|
|
78
82
|
' </header>',
|
|
79
83
|
` <iframe src="${filename}" title="Variant ${letter}" loading="lazy" class="block h-[720px] w-full bg-white"></iframe>`,
|
|
80
84
|
' <footer class="flex items-center justify-between gap-3 border-t border-slate-800 px-4 py-3">',
|
|
81
|
-
` <
|
|
85
|
+
` <a href="${filename}" target="_blank" rel="noopener" class="text-xs font-medium ${ACCENT} hover:underline">Open full size ↗</a>`,
|
|
82
86
|
` <code class="rounded bg-slate-800 px-2 py-1 text-xs text-slate-100">/apt:mockup --pick ${letter.toLowerCase()}</code>`,
|
|
83
87
|
' </footer>',
|
|
84
88
|
' </article>',
|
|
@@ -104,7 +108,7 @@ export function renderGallery(input) {
|
|
|
104
108
|
' <div>',
|
|
105
109
|
` <div class="text-xs uppercase tracking-[0.2em] text-slate-500">Variant gallery · iteration ${iterationEsc}</div>`,
|
|
106
110
|
` <h1 class="mt-1 text-2xl font-semibold text-slate-100">${featureEsc}</h1>`,
|
|
107
|
-
` <p class="mt-1 text-sm text-slate-400">${variants.length} parallel generations. Open this page via <code>file://</code>, scan the iframes, pick the letter that lands.</p>`,
|
|
111
|
+
` <p class="mt-1 text-sm text-slate-400">${variants.length} parallel generations. Open this page via <code>file://</code>, scan the iframes, click “Open full size” to view any variant in its own tab, then pick the letter that lands.</p>`,
|
|
108
112
|
' </div>',
|
|
109
113
|
' <div class="flex flex-col gap-2 text-xs text-slate-400 sm:items-end">',
|
|
110
114
|
` <div>Directory: <code class="text-slate-300">${taskDirEsc}/mockups/</code></div>`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gallery.mjs","sourceRoot":"","sources":["../../../src/cli/variant/gallery.mjs"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"gallery.mjs","sourceRoot":"","sources":["../../../src/cli/variant/gallery.mjs"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aperant",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"description": "AI coding framework — composable skills for planning, executing, verifying, and reviewing code with any LLM provider. Works as Claude Code commands, Codex tasks, or programmatically.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Mikalsen AI",
|
|
@@ -45,6 +45,7 @@
|
|
|
45
45
|
"skills/apt-personas",
|
|
46
46
|
"skills/apt-plan",
|
|
47
47
|
"skills/apt-pr-review",
|
|
48
|
+
"skills/apt-produce",
|
|
48
49
|
"skills/apt-prototype",
|
|
49
50
|
"skills/apt-quick",
|
|
50
51
|
"skills/apt-release-notes",
|
|
@@ -103,6 +103,12 @@ node packages/framework/bin/apt-tools.mjs commit "feat: {subtask.title}" --files
|
|
|
103
103
|
```
|
|
104
104
|
Update `implementation_plan.json` status to `"completed"`. Write `build-progress.json`.
|
|
105
105
|
|
|
106
|
+
**Delta-emit (feature registry).** After the commit, scaffold this subtask's registry delta and enrich it while the build context is still in your window:
|
|
107
|
+
```bash
|
|
108
|
+
node packages/framework/bin/apt-tools.mjs features-reconcile . --draft --task-id {task-id} --subtask-id {subtask.id}
|
|
109
|
+
```
|
|
110
|
+
Fill every `needs-disposition` entry (`upsert` / `remove` / `wiring-transition` / `no-semantic-change` — the last needs a one-line `reason`), assign any `area: null`, and replace draft upsert stubs with real `sub_features` carrying `wired`/`handler`/`test_hint`. Then stage the delta and amend it into the subtask commit: `git add .aperant/features/deltas/ && git commit --amend --no-edit`. Non-blocking: on a reconcile glitch, log and continue — the ship gate + CI check catch real gaps.
|
|
111
|
+
|
|
106
112
|
### 3f. Checkpoint State
|
|
107
113
|
`build-progress.json` is written every subtask in 3e — that is the durable resume point. Do NOT self-estimate context. Do NOT voluntarily exit. Keep executing until the plan is complete or a risk gate stops you. If the harness auto-compacts mid-run, re-read `{task_dir}/implementation_plan.json` + `{task_dir}/build-progress.json` after compaction and continue from the next pending subtask — the checkpoint is authoritative, your in-memory state is not.
|
|
108
114
|
|
|
@@ -190,8 +190,9 @@ Two policy buckets, two behaviors:
|
|
|
190
190
|
finding if you omit it.
|
|
191
191
|
- **`auto-update`** (default for milestones.json, REGISTRY.md,
|
|
192
192
|
project_index.json, .aperant/tasks/**): a doc subtask that invokes the
|
|
193
|
-
appropriate apt-tools subcommand (`features-
|
|
194
|
-
`roadmap rollup`, etc.) so the internal
|
|
193
|
+
appropriate apt-tools subcommand (`features-reconcile --draft` at the
|
|
194
|
+
executor's delta-emit step, `roadmap rollup`, etc.) so the internal
|
|
195
|
+
state stays coherent.
|
|
195
196
|
|
|
196
197
|
Bias toward false positives — a no-op doc subtask costs nothing; a missed
|
|
197
198
|
drift finding ships to the user. Full rules in
|
|
@@ -17,7 +17,7 @@ execution_modes:
|
|
|
17
17
|
- plan-mode
|
|
18
18
|
- plan-only
|
|
19
19
|
- research
|
|
20
|
-
allowed-tools: "Bash, Read, Grep, Glob,
|
|
20
|
+
allowed-tools: "Bash, Read, Grep, Glob, Task"
|
|
21
21
|
argument-hint: "[free-text task or /apt <skill> …]"
|
|
22
22
|
gates: []
|
|
23
23
|
---
|
|
@@ -234,12 +234,19 @@ Resolve the track, then create a fresh task record before invoking the skill.
|
|
|
234
234
|
- `plan` → `STANDARD`
|
|
235
235
|
- everything else with `task_context: create-new` → `STANDARD`
|
|
236
236
|
|
|
237
|
-
Then run:
|
|
237
|
+
Then run the deterministic allocator (NOT raw `task create`):
|
|
238
238
|
|
|
239
239
|
```bash
|
|
240
|
-
node packages/framework/bin/apt-tools.mjs task
|
|
240
|
+
node packages/framework/bin/apt-tools.mjs task ensure . --description "{slug}" --intent create-new --track {track} --autonomy {autonomy} [--scope {scope}]
|
|
241
241
|
```
|
|
242
242
|
|
|
243
|
+
`task ensure --intent create-new` is idempotent (re-running the same
|
|
244
|
+
input returns the SAME task + worktree, `reused: true`) and resolves the
|
|
245
|
+
effective autonomy from `config.autonomy.default` BEFORE provisioning the
|
|
246
|
+
worktree — so allocation is host-agnostic and never depends on this prose
|
|
247
|
+
being followed. The `allocation_intent` here is `create-new` because the
|
|
248
|
+
skill's `task_context` is `create-new` (the four-value taxonomy maps 1:1).
|
|
249
|
+
|
|
243
250
|
**Security note:** Do NOT interpolate `{skill_args}` directly into `--description "..."`. `skill_args` is verbatim user input and can contain double-quote characters that break out of the argument boundary and inject extra flags (e.g. `--autonomy`, `--scope`). The task slug is sufficient as the description; `skill_args` is passed to the skill separately after the task record is created.
|
|
244
251
|
|
|
245
252
|
(Use `--scope framework` only when the user is on a framework-scoped task —
|
|
@@ -300,29 +307,41 @@ The router emitted a `classify` envelope. This is the main routing path —
|
|
|
300
307
|
all free-text input and every flag-override (--quick/--deep/--debug) lands
|
|
301
308
|
here.
|
|
302
309
|
|
|
303
|
-
###
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
310
|
+
### allocation_intent — the single LLM bit (decide FIRST, before picking a skill)
|
|
311
|
+
|
|
312
|
+
The ONLY allocation judgment you make on the free-text path is a single
|
|
313
|
+
schema-bounded `allocation_intent ∈ {create-new | require-existing |
|
|
314
|
+
self-managed | none}` (the SAME four-value taxonomy as skill `task_context`).
|
|
315
|
+
**Fail-closed default is `none`** — when in doubt, allocate nothing. There is
|
|
316
|
+
no separate prose-only brainstorm gate that can bypass allocation; the
|
|
317
|
+
brainstorm decision is just the `none` outcome of this one judgment.
|
|
318
|
+
|
|
319
|
+
Map the user's input to one bit:
|
|
320
|
+
|
|
321
|
+
- **`none`** — vision / exploration / investigation / status / help. The user
|
|
322
|
+
wants to *explore a vision* or *ask a question*, not commit to a work item.
|
|
323
|
+
Allocate NOTHING (no task, no worktree) and dispatch to `apt:discuss
|
|
324
|
+
--brainstorm` (or the picked investigative skill). Signals — any one →
|
|
325
|
+
`none`:
|
|
326
|
+
- Vision statements: *"here's what I want to build"*, *"my goal is..."*, *"the idea is..."*
|
|
327
|
+
- Open invitations: *"let's think about"*, *"let's brainstorm"*, *"help me figure out"*, *"what's the best way..."*
|
|
328
|
+
- Paragraph-shaped input describing an outcome or direction, not a single work item
|
|
329
|
+
- Explicit "before we plan, let's explore / think / brainstorm..."
|
|
330
|
+
|
|
331
|
+
How to hand off:
|
|
332
|
+
```
|
|
333
|
+
[APT] allocation_intent=none (brainstorm/investigation) — routing to /apt:discuss --brainstorm
|
|
334
|
+
```
|
|
335
|
+
Then invoke `/apt:discuss --brainstorm` with the user's input and stop.
|
|
336
|
+
|
|
337
|
+
- **`self-managed`** — the picked skill owns its own task/worktree lifecycle
|
|
338
|
+
(e.g. `apt:run`, `apt:pr-review`). Allocate nothing here; let the skill do it.
|
|
339
|
+
- **`require-existing`** — the user is continuing an existing task. Do NOT mint;
|
|
340
|
+
resolve the active task (Step 2 uses `task ensure --intent require-existing`).
|
|
341
|
+
- **`create-new`** — concrete work item / specific deliverable that needs a
|
|
342
|
+
fresh task + worktree. Examples: *"add OAuth login"*, *"fix the view-tracking
|
|
343
|
+
bug"*, *"migrate reports to JSONB"*. Continue to Step 0; Step 2 provisions
|
|
344
|
+
deterministically via `task ensure --intent create-new`.
|
|
326
345
|
|
|
327
346
|
### Step 0a: Flag-override fast path (envelope.track is set)
|
|
328
347
|
|
|
@@ -332,6 +351,15 @@ carries `track`, `primary_skill`, `spawn_agent`, `agent`, and `options`.
|
|
|
332
351
|
**Skip Step 0b and Step 0c — go straight to Step 1.** These were locked
|
|
333
352
|
by the user typing `--quick` / `--deep` / `--debug`, not by the host LLM.
|
|
334
353
|
|
|
354
|
+
**allocation_intent (flag-override is deterministic — no LLM judgment):**
|
|
355
|
+
map `primary_skill` → `allocation_intent`:
|
|
356
|
+
- `quick` → `create-new`
|
|
357
|
+
- `debug` → `create-new`
|
|
358
|
+
- `plan` → `create-new` (STANDARD / DEEP)
|
|
359
|
+
- a skill whose `task_context` is `self-managed` (e.g. `run`) → `self-managed`
|
|
360
|
+
|
|
361
|
+
Step 2 forwards this bit to `task ensure --intent <bit>`.
|
|
362
|
+
|
|
335
363
|
### Step 0b: Classify the skill (envelope.skills[] inline pick)
|
|
336
364
|
|
|
337
365
|
When `classification.source: "host-model-deferred"` (free-text path),
|
|
@@ -405,15 +433,31 @@ Map choice: full auto → `execution_mode = "auto"`, step by step → `"step"`,
|
|
|
405
433
|
|
|
406
434
|
If `needs_autonomy_prompt` is false (user passed --yolo/--autonomous), skip this — use `execution_mode` from route result.
|
|
407
435
|
|
|
408
|
-
### Step 2: Register Task
|
|
436
|
+
### Step 2: Register Task (deterministic allocation)
|
|
437
|
+
|
|
438
|
+
Forward the `allocation_intent` decided above (Step 0a flag-override map,
|
|
439
|
+
or the free-text bit from the allocation_intent section) to the
|
|
440
|
+
deterministic, idempotent allocator — NOT raw `task create`:
|
|
409
441
|
|
|
410
442
|
```bash
|
|
411
|
-
node packages/framework/bin/apt-tools.mjs task
|
|
443
|
+
node packages/framework/bin/apt-tools.mjs task ensure . --description "{task_description}" --intent {allocation_intent} --track {track} --autonomy {autonomy}
|
|
412
444
|
```
|
|
413
445
|
|
|
446
|
+
- `--intent create-new` provisions a fresh task + worktree, idempotent on
|
|
447
|
+
re-run (`reused: true` returns the SAME task/worktree — re-issuing `/apt`
|
|
448
|
+
never duplicates). Effective autonomy is resolved from
|
|
449
|
+
`config.autonomy.default` BEFORE the worktree hook, so a
|
|
450
|
+
`from_branch: current` base is not spuriously deferred.
|
|
451
|
+
- `--intent require-existing` resolves the active task WITHOUT minting
|
|
452
|
+
(returns `requires_input` on ambiguity — fall back to the
|
|
453
|
+
skill-passthrough resolution chain prompt).
|
|
454
|
+
- `--intent none` / `--intent self-managed` allocate nothing
|
|
455
|
+
(`allocated: false`) — you should already have dispatched per the
|
|
456
|
+
allocation_intent section above and not reached Step 2.
|
|
457
|
+
|
|
414
458
|
Parse `task_id`, `task_dir`, and (if present) `worktree.worktree_path` / `worktree.branch` / `worktree.base_branch` from the result.
|
|
415
459
|
|
|
416
|
-
**Task-level worktree isolation:** when `task_isolation.worktree_per_task` is enabled (check via `host_capabilities.worktrees` + `task_isolation` in the route result) and `task
|
|
460
|
+
**Task-level worktree isolation:** when `task_isolation.worktree_per_task` is enabled (check via `host_capabilities.worktrees` + `task_isolation` in the route result) and `task ensure` returns a `worktree` block, every subsequent Bash call AND every spawned agent in this pipeline MUST use `worktree_path` as its working directory. Print:
|
|
417
461
|
|
|
418
462
|
```
|
|
419
463
|
[APT] Working in isolated worktree: {worktree_path}
|
|
@@ -424,7 +468,7 @@ Important nuances:
|
|
|
424
468
|
- `task_dir` is an **absolute path** under the main repo's `.aperant/tasks/{task-id}/`. All spec/plan/progress artifacts live there and are shared across worktrees.
|
|
425
469
|
- `apt-tools` commands still receive the **project root** as `<project-dir>` — they coordinate state through the main repo's `.aperant/`. The worktree only affects *code editing* cwd.
|
|
426
470
|
- When spawning an agent, set its `cwd` (or prefix its Bash calls with `cd {worktree_path} &&`) to the worktree for code reads/edits. Pass `worktree_path` in the agent's context so it knows where code work happens.
|
|
427
|
-
- Planner artifact safety: do **not** spawn `apt-planner` with host-level worktree isolation that gives it a separate copied repo. The planner must write `spec.md` and `implementation_plan.json` to the absolute main-repo `task_dir` from `task
|
|
471
|
+
- Planner artifact safety: do **not** spawn `apt-planner` with host-level worktree isolation that gives it a separate copied repo. The planner must write `spec.md` and `implementation_plan.json` to the absolute main-repo `task_dir` from `task ensure`; `.aperant/tasks/**` is gitignored, so artifacts written under a disposable worktree can be invisible to git and lost when that worktree is cleaned.
|
|
428
472
|
- If no `worktree` block is returned, proceed in the project root as before.
|
|
429
473
|
|
|
430
474
|
### Step 3: Spawn Planner Agent
|
|
@@ -482,14 +526,44 @@ tally output. Skip silently if tokens tally errors — never block the
|
|
|
482
526
|
pipeline on telemetry.
|
|
483
527
|
|
|
484
528
|
**If `spawn_agent` is false (QUICK or DEBUG):**
|
|
485
|
-
Both QUICK and DEBUG resolve here (single-shot, no spawned phase agent).
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
529
|
+
Both QUICK and DEBUG resolve here (single-shot, no spawned phase agent).
|
|
530
|
+
|
|
531
|
+
**The router itself CANNOT edit code.** Its frontmatter `allowed-tools` is
|
|
532
|
+
`Bash, Read, Grep, Glob, Task` — it has NO `Write` / `Edit` tool. This is the
|
|
533
|
+
load-bearing boundary (ID-05): the router can classify, allocate
|
|
534
|
+
(`task ensure`), and dispatch, but it can never edit a file on `main`.
|
|
535
|
+
|
|
536
|
+
So do NOT edit inline. **INVOKE the `apt:quick` / `apt:debug` SKILL** (per
|
|
537
|
+
`primary_skill`) AFTER Step 2's `task ensure --intent create-new` has
|
|
538
|
+
provisioned the worktree. Invoking the skill establishes that skill's OWN
|
|
539
|
+
`allowed-tools` scope (`apt-quick` / `apt-debug` both carry
|
|
540
|
+
`Read, Write, Edit, Bash, Grep, Glob`), which RE-GRANTS the edit affordance —
|
|
541
|
+
but only once a worktree exists, so editing can never land on `main` through
|
|
542
|
+
the router. Pass `task_id`, `task_dir`, AND `worktree_path` into the invoked
|
|
543
|
+
skill's context (thread `worktree_path` the same way the `spawn_agent: true`
|
|
544
|
+
branch threads it into the planner). This is a SKILL invocation, NOT a `Task`
|
|
545
|
+
sub-agent spawn — QUICK/DEBUG stay single-agent/single-context, so the Fast
|
|
546
|
+
Path Guarantee is preserved. No phase marker. (If Step 2 returned no `worktree`
|
|
547
|
+
block, pass `worktree_path` as "none" and the skill proceeds in the project
|
|
548
|
+
root.)
|
|
549
|
+
|
|
550
|
+
> **inline vs skill-scope (read this).** "Inline" here means the OLD behavior:
|
|
551
|
+
> the router editing within its own `/apt` turn under the router's allowlist.
|
|
552
|
+
> That is gone — the router has no edit tool. "Skill-scope" is the NEW
|
|
553
|
+
> behavior: a genuine `apt:quick` / `apt:debug` invocation whose own
|
|
554
|
+
> `allowed-tools` re-grants `Write, Edit` for the edit work, after the worktree
|
|
555
|
+
> exists.
|
|
556
|
+
>
|
|
557
|
+
> **Residual (host-runtime, not CI-provable — founder smoke-test gate).**
|
|
558
|
+
> Whether Claude Code treats a nested skill's `allowed-tools` as a REPLACEMENT
|
|
559
|
+
> (re-grants edit — design holds) or as an INTERSECTION/ceiling (the parent
|
|
560
|
+
> router allowlist caps the child — Fast Path breaks) is a host-implementation
|
|
561
|
+
> property that cannot be unit-tested from the framework. CI proves the
|
|
562
|
+
> frontmatter/prose structure; a founder in-app smoke-test is the residual gate.
|
|
563
|
+
> **Fallback if the smoke-test shows breakage:** revert ONLY the
|
|
564
|
+
> router-frontmatter line (re-add `Write, Edit`). The host-agnostic
|
|
565
|
+
> `task ensure` boundary (ID-02) still fixes the on-`main`-edit bug; the
|
|
566
|
+
> allowed-tools removal is hardening, not the fix.
|
|
493
567
|
|
|
494
568
|
### Step 4: Chain Pipeline (based on selected option)
|
|
495
569
|
|
|
@@ -185,7 +185,7 @@ Flags:
|
|
|
185
185
|
Per ledger entry `{ task_id, scope, phase_id, closed_at, pr_number }`:
|
|
186
186
|
|
|
187
187
|
0. **Enumerate the ledger first.** Run `apt-tools task close-merged . --narrate-only [--task <id>]`. The envelope's `closed[]` is the read-only list of pending narration rows (each carries `narration_pending: true`); state.json is not mutated. When `closed[]` is empty, exit early with `{status: 'ok', narrated: [], skipped: [], remaining: 0}` — there is nothing to drain.
|
|
188
|
-
1. Run `apt-tools features-
|
|
188
|
+
1. Run `apt-tools features-reconcile . --gc` to prune feature-registry receipts that are merged to origin/main and older than 30 days. Receipt GC is close-task's ONLY registry role — the registry WRITE happened at ship time (`/apt:ship` §0.0 materialize), so there is no post-merge registry write to drift main. If the subprocess exits non-zero, skip the entry with `reason: 'features-gc-failed'` — never block narration on registry GC.
|
|
189
189
|
2. When `phase_id` is non-null, spawn `apt-team-docs-narrator` (background, fire-and-forget) using the same shape as §2.5: `subagent_type: apt-team-docs-narrator`, `run_in_background: true`, `description: Narrate shipped phase {phase_id}`, `prompt: Run in phase-ship mode with --phase {phase_id} --scope {scope}.`. When `phase_id` is null, skip the spawn with `reason: 'no-phase-id'` (quick tasks have no phase to narrate).
|
|
190
190
|
3. On successful spawn (or successful no-phase skip), drain the row via `apt-tools task narration-drain . --task <task_id>` which acquires `withFileLock(state.json)` and removes the matching `pending_narration[]` entry. On spawn failure, leave the row in place with `reason: 'narrator-spawn-failed'` so the user can re-invoke.
|
|
191
191
|
|
|
@@ -198,7 +198,7 @@ Emit a summary envelope:
|
|
|
198
198
|
"status": "ok",
|
|
199
199
|
"command": "close-task-narrate-only",
|
|
200
200
|
"narrated": [{ "task_id": "<id>", "phase_id": "<p|null>", "scope": "<s>" }],
|
|
201
|
-
"skipped": [{ "task_id": "<id>", "reason": "no-phase-id|features-
|
|
201
|
+
"skipped": [{ "task_id": "<id>", "reason": "no-phase-id|features-gc-failed|narrator-spawn-failed" }],
|
|
202
202
|
"remaining": <ledger.length>
|
|
203
203
|
}
|
|
204
204
|
```
|