@aperant/framework 0.17.0 → 0.19.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 +152 -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/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 +2 -0
- package/dist/cli/dispatch.mjs.map +1 -1
- package/dist/cli/help.d.mts.map +1 -1
- package/dist/cli/help.mjs +30 -0
- 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/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/plugin/.claude-plugin/plugin.json +2 -1
- package/dist/plugin/skills/apt/SKILL.md +112 -38
- package/dist/plugin/skills/apt-debug/SKILL.md +14 -24
- 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-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 +14 -22
- package/dist/plugin/skills/apt-run/SKILL.md +126 -3
- package/dist/plugin/skills/apt-ship/SKILL.md +2 -0
- package/dist/plugin/skills/apt-spar/SKILL.md +5 -3
- package/dist/plugin/skills/apt-watch-ci/SKILL.md +4 -4
- 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-debug/SKILL.md +14 -24
- package/skills/apt-fan-out/SKILL.md +4 -4
- package/skills/apt-handoff/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 +14 -22
- package/skills/apt-run/SKILL.md +126 -3
- package/skills/apt-ship/SKILL.md +2 -0
- package/skills/apt-spar/SKILL.md +5 -3
- package/skills/apt-watch-ci/SKILL.md +4 -4
- 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/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 +2 -0
- package/src/cli/help.mjs +30 -0
- 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/roadmap/showrunner-view.d.ts +10 -0
- package/src/cli/roadmap/{conductor-view.mjs → showrunner-view.mjs} +6 -6
- package/dist/cli/roadmap/conductor-view.d.mts.map +0 -1
- package/dist/cli/roadmap/conductor-view.mjs.map +0 -1
- package/src/cli/roadmap/conductor-view.d.ts +0 -10
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @internal
|
|
3
|
+
* produce/saga.mjs — the plan→execute→verify→review→ship saga + FORWARD
|
|
4
|
+
* compensators (M4, ID-M4-01 / ID-M4-02, the ID-10 semantic).
|
|
5
|
+
*
|
|
6
|
+
* The loop is modeled as a saga: each phase declares a FORWARD compensator via
|
|
7
|
+
* `resolveCompensator(phase)`. The load-bearing invariant is that EVERY
|
|
8
|
+
* compensator carries `rolls_back_merged_pr: false` — a compensator is always a
|
|
9
|
+
* forward compensating transaction. A failed verify/review/ship SHIPS A REVERT
|
|
10
|
+
* (a new forward commit/branch) + reopens the task + re-plans; it NEVER un-merges
|
|
11
|
+
* history other agents/humans already built on. plan/execute are pre-merge and
|
|
12
|
+
* simply reopen + re-plan (no revert), still `rolls_back_merged_pr: false`.
|
|
13
|
+
*
|
|
14
|
+
* The CLI RECORDS the phase transitions + the forward-compensator DESCRIPTOR; it
|
|
15
|
+
* NEVER executes the revert / reopen / re-plan (that dispatch is OOS — the CLI
|
|
16
|
+
* records + computes, the skill/dispatch acts, exactly as M2 records
|
|
17
|
+
* oracle/probe results while the skill drives the LLM steps).
|
|
18
|
+
*
|
|
19
|
+
* `projectSaga` folds `produce.saga.*` ONLY into per-milestone phase state — a
|
|
20
|
+
* SEPARATE fold PARALLEL to the roadmap projection (projection.mjs still folds
|
|
21
|
+
* `produce.roadmap.*` ONLY, so the M1/M2/M3 blindness invariant holds: a saga
|
|
22
|
+
* compensation never mutates a milestone's `done` roadmap status).
|
|
23
|
+
*/
|
|
24
|
+
import { appendProduceEvent, readImplementerFamily, readProduceRunEventsMatching, } from './events.mjs';
|
|
25
|
+
import { normalizeFamily, resolveProbeFamily } from './probe-family.mjs';
|
|
26
|
+
/** The ordered saga phases (ID-M4-01). Mirrors ALLOWED_SAGA_PHASES in event-schema.mjs. */
|
|
27
|
+
export const SAGA_PHASES = ['plan', 'execute', 'verify', 'review', 'ship'];
|
|
28
|
+
/**
|
|
29
|
+
* The declared FORWARD-compensator table (ID-M4-02). EVERY descriptor carries
|
|
30
|
+
* `rolls_back_merged_pr: false` — a compensator is always forward. plan/execute
|
|
31
|
+
* are pre-merge (reopen + re-plan, no revert); verify/review/ship SHIP A REVERT
|
|
32
|
+
* + reopen + re-plan. The CLI records the descriptor kind; it never emits a
|
|
33
|
+
* rollback / history-rewrite instruction.
|
|
34
|
+
*/
|
|
35
|
+
const COMPENSATORS = {
|
|
36
|
+
plan: {
|
|
37
|
+
kind: 'rewrite_plan',
|
|
38
|
+
reopens_task: true,
|
|
39
|
+
ships_revert: false,
|
|
40
|
+
rolls_back_merged_pr: false,
|
|
41
|
+
},
|
|
42
|
+
execute: {
|
|
43
|
+
kind: 'discard_branch_replan',
|
|
44
|
+
reopens_task: true,
|
|
45
|
+
ships_revert: false,
|
|
46
|
+
rolls_back_merged_pr: false,
|
|
47
|
+
},
|
|
48
|
+
verify: {
|
|
49
|
+
kind: 'revert_reopen_replan',
|
|
50
|
+
reopens_task: true,
|
|
51
|
+
ships_revert: true,
|
|
52
|
+
rolls_back_merged_pr: false,
|
|
53
|
+
},
|
|
54
|
+
review: {
|
|
55
|
+
kind: 'revert_reopen_replan',
|
|
56
|
+
reopens_task: true,
|
|
57
|
+
ships_revert: true,
|
|
58
|
+
rolls_back_merged_pr: false,
|
|
59
|
+
},
|
|
60
|
+
ship: {
|
|
61
|
+
kind: 'revert_reopen_replan',
|
|
62
|
+
reopens_task: true,
|
|
63
|
+
ships_revert: true,
|
|
64
|
+
rolls_back_merged_pr: false,
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Resolve the declared FORWARD compensator for a saga phase. Returns a fresh
|
|
69
|
+
* copy (the table is never handed out mutable) or null for an out-of-vocabulary
|
|
70
|
+
* phase (fail-closed). The returned descriptor ALWAYS has
|
|
71
|
+
* `rolls_back_merged_pr: false` (ID-M4-02).
|
|
72
|
+
*
|
|
73
|
+
* @param {string} phase
|
|
74
|
+
* @returns {{ kind: string, reopens_task: boolean, ships_revert: boolean, rolls_back_merged_pr: boolean } | null}
|
|
75
|
+
*/
|
|
76
|
+
export function resolveCompensator(phase) {
|
|
77
|
+
const descriptor = COMPENSATORS[phase];
|
|
78
|
+
if (!descriptor)
|
|
79
|
+
return null;
|
|
80
|
+
return { ...descriptor };
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Append `produce.saga.phase_entered` for a milestone's saga phase. Validates
|
|
84
|
+
* the phase against SAGA_PHASES fail-closed (an out-of-vocabulary phase appends
|
|
85
|
+
* nothing).
|
|
86
|
+
*
|
|
87
|
+
* @param {string} projectDir
|
|
88
|
+
* @param {{ runId: string, milestoneId: string, phase: string }} args
|
|
89
|
+
* @returns {{ ok: true, phase: string } | { ok: false, reason: string }}
|
|
90
|
+
*/
|
|
91
|
+
export function enterPhase(projectDir, { runId, milestoneId, phase }) {
|
|
92
|
+
if (!SAGA_PHASES.includes(phase))
|
|
93
|
+
return { ok: false, reason: 'invalid_phase' };
|
|
94
|
+
appendProduceEvent(projectDir, 'produce.saga.phase_entered', {
|
|
95
|
+
run_id: runId,
|
|
96
|
+
milestone_id: milestoneId,
|
|
97
|
+
phase,
|
|
98
|
+
});
|
|
99
|
+
return { ok: true, phase };
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Append `produce.saga.phase_completed` for a milestone's saga phase. Validates
|
|
103
|
+
* the phase against SAGA_PHASES fail-closed.
|
|
104
|
+
*
|
|
105
|
+
* @param {string} projectDir
|
|
106
|
+
* @param {{ runId: string, milestoneId: string, phase: string }} args
|
|
107
|
+
* @returns {{ ok: true, phase: string } | { ok: false, reason: string }}
|
|
108
|
+
*/
|
|
109
|
+
export function completePhase(projectDir, { runId, milestoneId, phase }) {
|
|
110
|
+
if (!SAGA_PHASES.includes(phase))
|
|
111
|
+
return { ok: false, reason: 'invalid_phase' };
|
|
112
|
+
appendProduceEvent(projectDir, 'produce.saga.phase_completed', {
|
|
113
|
+
run_id: runId,
|
|
114
|
+
milestone_id: milestoneId,
|
|
115
|
+
phase,
|
|
116
|
+
});
|
|
117
|
+
return { ok: true, phase };
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Fire the FORWARD compensator for a failed saga phase (ID-M4-02). Resolves the
|
|
121
|
+
* declared compensator, then appends `produce.saga.compensated {run_id,
|
|
122
|
+
* milestone_id, phase, compensator: <descriptor.kind>, reason}` — carrying the
|
|
123
|
+
* descriptor KIND, never a rollback instruction. Validates the phase fail-closed.
|
|
124
|
+
* The CLI records the forward compensator; it does NOT execute the revert/reopen/
|
|
125
|
+
* re-plan (OOS dispatch) and NEVER mutates the roadmap milestone status.
|
|
126
|
+
*
|
|
127
|
+
* @param {string} projectDir
|
|
128
|
+
* @param {{ runId: string, milestoneId: string, phase: string, reason?: string }} args
|
|
129
|
+
* @returns {{ ok: true, phase: string, compensator: object } | { ok: false, reason: string }}
|
|
130
|
+
*/
|
|
131
|
+
export function compensatePhase(projectDir, { runId, milestoneId, phase, reason }) {
|
|
132
|
+
if (!SAGA_PHASES.includes(phase))
|
|
133
|
+
return { ok: false, reason: 'invalid_phase' };
|
|
134
|
+
const compensator = resolveCompensator(phase);
|
|
135
|
+
appendProduceEvent(projectDir, 'produce.saga.compensated', {
|
|
136
|
+
run_id: runId,
|
|
137
|
+
milestone_id: milestoneId,
|
|
138
|
+
phase,
|
|
139
|
+
compensator: compensator.kind,
|
|
140
|
+
reason: reason || `compensate_${phase}`,
|
|
141
|
+
});
|
|
142
|
+
return { ok: true, phase, compensator };
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Record a provider-diverse review verdict (ID-M4-04 / ID-08). The review-path
|
|
146
|
+
* analog of evidence-oracle.mjs::recordOracleVerdict. REFUSES fail-closed when
|
|
147
|
+
* the reviewer family equals the recorded implementer family (a same-family
|
|
148
|
+
* reviewer rubber-stamps its own family's work) or when no implementer family is
|
|
149
|
+
* recorded (ID-M2-02). On acceptance appends `produce.saga.reviewed {run_id,
|
|
150
|
+
* milestone_id, reviewer_family, verdict}`.
|
|
151
|
+
*
|
|
152
|
+
* @param {string} projectDir
|
|
153
|
+
* @param {{ runId: string, milestoneId: string, verdict: string, reviewerFamily: string }} args
|
|
154
|
+
* @returns {{ ok: true, verdict: string, reviewer_family: string, implementer_family: string }
|
|
155
|
+
* | { ok: false, reason: string, implementer_family?: string | null }}
|
|
156
|
+
*/
|
|
157
|
+
export function recordReview(projectDir, { runId, milestoneId, verdict, reviewerFamily }) {
|
|
158
|
+
if (verdict !== 'pass' && verdict !== 'fail')
|
|
159
|
+
return { ok: false, reason: 'invalid_verdict' };
|
|
160
|
+
if (!reviewerFamily)
|
|
161
|
+
return { ok: false, reason: 'no_reviewer_family' };
|
|
162
|
+
const implementerFamily = readImplementerFamily(projectDir, runId, milestoneId);
|
|
163
|
+
if (!implementerFamily)
|
|
164
|
+
return { ok: false, reason: 'no_recorded_implementer', implementer_family: null };
|
|
165
|
+
// Cross-family enforcement (normalized so claude-code === claude).
|
|
166
|
+
if (normalizeFamily(reviewerFamily) === normalizeFamily(implementerFamily))
|
|
167
|
+
return { ok: false, reason: 'same_family_reviewer', implementer_family: implementerFamily };
|
|
168
|
+
appendProduceEvent(projectDir, 'produce.saga.reviewed', {
|
|
169
|
+
run_id: runId,
|
|
170
|
+
milestone_id: milestoneId,
|
|
171
|
+
reviewer_family: reviewerFamily,
|
|
172
|
+
verdict,
|
|
173
|
+
});
|
|
174
|
+
return {
|
|
175
|
+
ok: true,
|
|
176
|
+
verdict,
|
|
177
|
+
reviewer_family: reviewerFamily,
|
|
178
|
+
implementer_family: implementerFamily,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Resolve a REVIEW-phase reviewer family DISJOINT from the recorded implementer
|
|
183
|
+
* (ID-M4-04 / ID-08), a THIN wrapper over the M2 `resolveProbeFamily` — NO
|
|
184
|
+
* duplicated cross-family / partner-map / model-resolution logic. Reads the
|
|
185
|
+
* implementer family from the recorded `produce.milestone.implemented` trail
|
|
186
|
+
* (fail-closed when absent). Returns the resolution with `probe_family` surfaced
|
|
187
|
+
* as `reviewer_family`. Provider is an OUTPUT; the model is resolved LIVE (null
|
|
188
|
+
* for self-resolving families) — never a hardcoded id.
|
|
189
|
+
*
|
|
190
|
+
* @param {string} projectDir
|
|
191
|
+
* @param {{ runId: string, milestoneId: string, hostFamily?: string | null, availableFamilies?: string[] }} args
|
|
192
|
+
* @returns {{ available: boolean, reviewer_family: string | null, implementer_family: string | null,
|
|
193
|
+
* transport_hint: object | null, model: string | null, source: string | null, reason: string | null }}
|
|
194
|
+
*/
|
|
195
|
+
export function resolveReviewer(projectDir, { runId, milestoneId, hostFamily, availableFamilies }) {
|
|
196
|
+
const implementerFamily = readImplementerFamily(projectDir, runId, milestoneId);
|
|
197
|
+
if (!implementerFamily) {
|
|
198
|
+
return {
|
|
199
|
+
available: false,
|
|
200
|
+
reviewer_family: null,
|
|
201
|
+
implementer_family: null,
|
|
202
|
+
transport_hint: null,
|
|
203
|
+
model: null,
|
|
204
|
+
source: null,
|
|
205
|
+
reason: 'no_recorded_implementer',
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
const resolution = resolveProbeFamily({ implementerFamily, hostFamily, availableFamilies });
|
|
209
|
+
// Surface the disjoint probe family as the reviewer family (same selection).
|
|
210
|
+
const { probe_family, ...rest } = resolution;
|
|
211
|
+
return { ...rest, reviewer_family: probe_family, implementer_family: implementerFamily };
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Fold the run's `produce.saga.*` events into per-milestone saga state — a
|
|
215
|
+
* SEPARATE fold parallel to the roadmap projection (the roadmap projection folds
|
|
216
|
+
* `produce.roadmap.*` ONLY, so saga events never enter the roadmap the Showrunner
|
|
217
|
+
* re-reads each tick — blindness preserved, ID-M4-01). Deterministic: two folds
|
|
218
|
+
* of the same log yield the identical saga state; `updated_at` is the last folded
|
|
219
|
+
* event's timestamp.
|
|
220
|
+
*
|
|
221
|
+
* @param {string} projectDir
|
|
222
|
+
* @param {string} runId
|
|
223
|
+
* @returns {{
|
|
224
|
+
* run_id: string,
|
|
225
|
+
* milestones: Array<{
|
|
226
|
+
* milestone_id: string,
|
|
227
|
+
* current_phase: string | null,
|
|
228
|
+
* phase_status: 'entered' | 'completed' | null,
|
|
229
|
+
* phases: Record<string, 'entered' | 'completed'>,
|
|
230
|
+
* last_compensated: { phase: string | null, compensator: string | null, reason: string | null } | null,
|
|
231
|
+
* reviewed: { reviewer_family: string | null, verdict: string | null } | null,
|
|
232
|
+
* }>,
|
|
233
|
+
* updated_at: string | null,
|
|
234
|
+
* }}
|
|
235
|
+
*/
|
|
236
|
+
export function projectSaga(projectDir, runId) {
|
|
237
|
+
const events = readProduceRunEventsMatching(projectDir, runId, (op) => op.startsWith('produce.saga.'));
|
|
238
|
+
const byId = new Map();
|
|
239
|
+
const order = [];
|
|
240
|
+
let updatedAt = null;
|
|
241
|
+
const ensure = (id) => {
|
|
242
|
+
if (!byId.has(id)) {
|
|
243
|
+
byId.set(id, {
|
|
244
|
+
milestone_id: id,
|
|
245
|
+
current_phase: null,
|
|
246
|
+
phase_status: null,
|
|
247
|
+
phases: {},
|
|
248
|
+
last_compensated: null,
|
|
249
|
+
reviewed: null,
|
|
250
|
+
});
|
|
251
|
+
order.push(id);
|
|
252
|
+
}
|
|
253
|
+
return byId.get(id);
|
|
254
|
+
};
|
|
255
|
+
for (const e of events) {
|
|
256
|
+
const d = e.data || {};
|
|
257
|
+
const id = typeof d.milestone_id === 'string' ? d.milestone_id : null;
|
|
258
|
+
if (!id)
|
|
259
|
+
continue;
|
|
260
|
+
const m = ensure(id);
|
|
261
|
+
const phase = typeof d.phase === 'string' ? d.phase : null;
|
|
262
|
+
if (e.op === 'produce.saga.phase_entered' && phase) {
|
|
263
|
+
m.current_phase = phase;
|
|
264
|
+
m.phase_status = 'entered';
|
|
265
|
+
m.phases[phase] = 'entered';
|
|
266
|
+
}
|
|
267
|
+
else if (e.op === 'produce.saga.phase_completed' && phase) {
|
|
268
|
+
m.current_phase = phase;
|
|
269
|
+
m.phase_status = 'completed';
|
|
270
|
+
m.phases[phase] = 'completed';
|
|
271
|
+
}
|
|
272
|
+
else if (e.op === 'produce.saga.compensated') {
|
|
273
|
+
m.last_compensated = {
|
|
274
|
+
phase,
|
|
275
|
+
compensator: typeof d.compensator === 'string' ? d.compensator : null,
|
|
276
|
+
reason: typeof d.reason === 'string' ? d.reason : null,
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
else if (e.op === 'produce.saga.reviewed') {
|
|
280
|
+
m.reviewed = {
|
|
281
|
+
reviewer_family: typeof d.reviewer_family === 'string' ? d.reviewer_family : null,
|
|
282
|
+
verdict: typeof d.verdict === 'string' ? d.verdict : null,
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
if (typeof e.t === 'string')
|
|
286
|
+
updatedAt = e.t;
|
|
287
|
+
}
|
|
288
|
+
return { run_id: runId, milestones: order.map((id) => byId.get(id)), updated_at: updatedAt };
|
|
289
|
+
}
|
|
290
|
+
//# sourceMappingURL=saga.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"saga.mjs","sourceRoot":"","sources":["../../../src/cli/produce/saga.mjs"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve the WIP cap deterministically (ID-M5-05):
|
|
3
|
+
* `--wip <n>` flag → `.aperant/config.json :: produce.wip` → default 1. A
|
|
4
|
+
* non-numeric / negative / bare `--wip` value is ignored (falls through). The
|
|
5
|
+
* cap is the max number of CONCURRENT in_progress milestones the loop will run.
|
|
6
|
+
*
|
|
7
|
+
* @param {string} projectDir
|
|
8
|
+
* @param {Map<string, string | true>} flags
|
|
9
|
+
* @returns {number}
|
|
10
|
+
*/
|
|
11
|
+
export function resolveWipLimit(projectDir: string, flags: Map<string, string | true>): number;
|
|
12
|
+
/**
|
|
13
|
+
* Fold the run's `produce.roadmap.milestone_added` events into the per-milestone
|
|
14
|
+
* scheduling metadata carried as ADDITIVE optional fields on that event
|
|
15
|
+
* (ID-M5-03): `depends_on` (string[]), `priority` (int, default 0), `size`
|
|
16
|
+
* (positive int | null). An M1-style milestone (added with no new flags) folds
|
|
17
|
+
* to `{ depends_on: [], priority: 0, size: null }` — byte-identical behavior.
|
|
18
|
+
* First-seen wins (idempotent re-adds never clobber).
|
|
19
|
+
*
|
|
20
|
+
* @param {string} projectDir
|
|
21
|
+
* @param {string} runId
|
|
22
|
+
* @returns {Map<string, { depends_on: string[], priority: number, size: number | null }>}
|
|
23
|
+
*/
|
|
24
|
+
export function readMilestoneMeta(projectDir: string, runId: string): Map<string, {
|
|
25
|
+
depends_on: string[];
|
|
26
|
+
priority: number;
|
|
27
|
+
size: number | null;
|
|
28
|
+
}>;
|
|
29
|
+
/**
|
|
30
|
+
* CostOfDelay = 5·regression + 3·blocking + 2·open_criteria + priority (all
|
|
31
|
+
* integer). Absent fields default to 0.
|
|
32
|
+
*
|
|
33
|
+
* @param {{ regressionFlag?: number, blockingCount?: number, openCriteria?: number, priority?: number }} args
|
|
34
|
+
* @returns {number}
|
|
35
|
+
*/
|
|
36
|
+
export function computeCostOfDelay({ regressionFlag, blockingCount, openCriteria, priority, }?: {
|
|
37
|
+
regressionFlag?: number;
|
|
38
|
+
blockingCount?: number;
|
|
39
|
+
openCriteria?: number;
|
|
40
|
+
priority?: number;
|
|
41
|
+
}): number;
|
|
42
|
+
/**
|
|
43
|
+
* JobSize = declared_size when positive, else the open-criteria count floored at
|
|
44
|
+
* 1 (never 0 — a criteria-less, size-less milestone is the smallest job = 1, so
|
|
45
|
+
* WSJF never divides by zero). ID-M5-01.
|
|
46
|
+
*
|
|
47
|
+
* @param {{ declaredSize?: number | null, openCriteria?: number }} args
|
|
48
|
+
* @returns {number}
|
|
49
|
+
*/
|
|
50
|
+
export function computeJobSize({ declaredSize, openCriteria }?: {
|
|
51
|
+
declaredSize?: number | null;
|
|
52
|
+
openCriteria?: number;
|
|
53
|
+
}): number;
|
|
54
|
+
/**
|
|
55
|
+
* WSJF = CostOfDelay / JobSize. JobSize is guaranteed ≥ 1 (computeJobSize) so
|
|
56
|
+
* this never divides by zero.
|
|
57
|
+
*
|
|
58
|
+
* @param {number} costOfDelay
|
|
59
|
+
* @param {number} jobSize
|
|
60
|
+
* @returns {number}
|
|
61
|
+
*/
|
|
62
|
+
export function computeWsjf(costOfDelay: number, jobSize: number): number;
|
|
63
|
+
/**
|
|
64
|
+
* True iff milestone `milestoneId` has an UNRESOLVED M4 verification-TTL
|
|
65
|
+
* regression — it appears in `listRegressions` AND its latest recorded
|
|
66
|
+
* `produce.ttl.reverified` result is not `pass` (ID-M5-07). A subsequent
|
|
67
|
+
* `--result pass` re-verify resolves it (latest result becomes `pass`).
|
|
68
|
+
*
|
|
69
|
+
* @param {string} projectDir
|
|
70
|
+
* @param {string} runId
|
|
71
|
+
* @param {string} milestoneId
|
|
72
|
+
* @returns {boolean}
|
|
73
|
+
*/
|
|
74
|
+
export function hasUnresolvedRegression(projectDir: string, runId: string, milestoneId: string): boolean;
|
|
75
|
+
/**
|
|
76
|
+
* A ranked ready-queue entry with its WSJF terms exposed.
|
|
77
|
+
*
|
|
78
|
+
* @typedef {Object} ScheduleEntry
|
|
79
|
+
* @property {string} milestone_id
|
|
80
|
+
* @property {string} title
|
|
81
|
+
* @property {string} status
|
|
82
|
+
* @property {number} wsjf
|
|
83
|
+
* @property {number} cost_of_delay
|
|
84
|
+
* @property {number} job_size
|
|
85
|
+
* @property {number} open_criteria
|
|
86
|
+
* @property {number} blocking_count
|
|
87
|
+
* @property {number} priority
|
|
88
|
+
* @property {boolean} regressed
|
|
89
|
+
*/
|
|
90
|
+
/**
|
|
91
|
+
* The pure schedule combiner (ID-M5-02). Folds the existing projections + the
|
|
92
|
+
* meta-fold + regressions into a WSJF-ranked `ready_queue`, a `blocked` list
|
|
93
|
+
* (with `blocked_by` = the not-done deps), the `in_progress` accounting, and a
|
|
94
|
+
* WIP-limited `pick` of the top `wip_available` ready milestones. Emits NO
|
|
95
|
+
* event and mutates no module (a pure read).
|
|
96
|
+
*
|
|
97
|
+
* Ready-set membership: a `planned` milestone is READY iff every `depends_on`
|
|
98
|
+
* id resolves to a roadmap milestone with status `done` (an unknown dep fails
|
|
99
|
+
* closed = unmet); otherwise it goes to `blocked`. A `done` milestone with an
|
|
100
|
+
* unresolved M4 regression re-enters the ready set tagged regressed:true.
|
|
101
|
+
*
|
|
102
|
+
* @param {string} projectDir
|
|
103
|
+
* @param {string} runId
|
|
104
|
+
* @param {{ wipLimit?: number }} [opts]
|
|
105
|
+
* @returns {{
|
|
106
|
+
* run_id: string,
|
|
107
|
+
* wip_limit: number,
|
|
108
|
+
* wip_in_use: number,
|
|
109
|
+
* wip_available: number,
|
|
110
|
+
* ready_queue: ScheduleEntry[],
|
|
111
|
+
* blocked: Array<{ milestone_id: string, title: string, blocked_by: string[] }>,
|
|
112
|
+
* in_progress: Array<{ milestone_id: string, title: string }>,
|
|
113
|
+
* pick: ScheduleEntry[],
|
|
114
|
+
* reason: string,
|
|
115
|
+
* cycle: string[] | null,
|
|
116
|
+
* }}
|
|
117
|
+
*/
|
|
118
|
+
export function computeSchedule(projectDir: string, runId: string, { wipLimit }?: {
|
|
119
|
+
wipLimit?: number;
|
|
120
|
+
}): {
|
|
121
|
+
run_id: string;
|
|
122
|
+
wip_limit: number;
|
|
123
|
+
wip_in_use: number;
|
|
124
|
+
wip_available: number;
|
|
125
|
+
ready_queue: ScheduleEntry[];
|
|
126
|
+
blocked: Array<{
|
|
127
|
+
milestone_id: string;
|
|
128
|
+
title: string;
|
|
129
|
+
blocked_by: string[];
|
|
130
|
+
}>;
|
|
131
|
+
in_progress: Array<{
|
|
132
|
+
milestone_id: string;
|
|
133
|
+
title: string;
|
|
134
|
+
}>;
|
|
135
|
+
pick: ScheduleEntry[];
|
|
136
|
+
reason: string;
|
|
137
|
+
cycle: string[] | null;
|
|
138
|
+
};
|
|
139
|
+
/**
|
|
140
|
+
* WSJF cost-of-delay weights (ID-M5-01). Fixed integer constants — the ordering
|
|
141
|
+
* is intentional: a shipped-but-regressed milestone is user-facing breakage
|
|
142
|
+
* (most urgent) > a milestone blocking many downstream ones > a milestone with
|
|
143
|
+
* more open value locked behind it > a human-declared priority nudge.
|
|
144
|
+
*/
|
|
145
|
+
export const W_REGRESS: 5;
|
|
146
|
+
export const W_BLOCK: 3;
|
|
147
|
+
export const W_VALUE: 2;
|
|
148
|
+
/** The default WIP cap when neither a flag nor config supplies one (ID-M5-05). */
|
|
149
|
+
export const DEFAULT_WIP_LIMIT: 1;
|
|
150
|
+
/**
|
|
151
|
+
* A ranked ready-queue entry with its WSJF terms exposed.
|
|
152
|
+
*/
|
|
153
|
+
export type ScheduleEntry = {
|
|
154
|
+
milestone_id: string;
|
|
155
|
+
title: string;
|
|
156
|
+
status: string;
|
|
157
|
+
wsjf: number;
|
|
158
|
+
cost_of_delay: number;
|
|
159
|
+
job_size: number;
|
|
160
|
+
open_criteria: number;
|
|
161
|
+
blocking_count: number;
|
|
162
|
+
priority: number;
|
|
163
|
+
regressed: boolean;
|
|
164
|
+
};
|
|
165
|
+
//# sourceMappingURL=scheduler.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.d.mts","sourceRoot":"","sources":["../../../src/cli/produce/scheduler.mjs"],"names":[],"mappings":"AAuEA;;;;;;;;;GASG;AACH,4CAJW,MAAM,SACN,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,GACxB,MAAM,CAelB;AAED;;;;;;;;;;;GAWG;AACH,8CAJW,MAAM,SACN,MAAM,GACJ,GAAG,CAAC,MAAM,EAAE;IAAE,UAAU,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAqBxF;AAED;;;;;;GAMG;AACH,gGAHW;IAAE,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3F,MAAM,CAclB;AAED;;;;;;;GAOG;AACH,gEAHW;IAAE,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,GACrD,MAAM,CAMlB;AAED;;;;;;;GAOG;AACH,yCAJW,MAAM,WACN,MAAM,GACJ,MAAM,CAIlB;AAED;;;;;;;;;;GAUG;AACH,oDALW,MAAM,SACN,MAAM,eACN,MAAM,GACJ,OAAO,CAgBnB;AAED;;;;;;;;;;;;;;GAcG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,4CAhBW,MAAM,SACN,MAAM,iBACN;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GACnB;IACR,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,aAAa,EAAE,CAAC;IAC7B,OAAO,EAAE,KAAK,CAAC;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IAC9E,WAAW,EAAE,KAAK,CAAC;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5D,IAAI,EAAE,aAAa,EAAE,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;CACxB,CA6GH;AA1TD;;;;;GAKG;AACH,wBAAyB,CAAC,CAAA;AAC1B,sBAAuB,CAAC,CAAA;AACxB,sBAAuB,CAAC,CAAA;AAExB,kFAAkF;AAClF,gCAAiC,CAAC,CAAA;;;;;kBA4JpB,MAAM;WACN,MAAM;YACN,MAAM;UACN,MAAM;mBACN,MAAM;cACN,MAAM;mBACN,MAAM;oBACN,MAAM;cACN,MAAM;eACN,OAAO"}
|