mandrel 2.37.0 → 2.38.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/.agents/README.md +16 -16
- package/.agents/agents/plan-critic.md +1 -1
- package/.agents/docs/SDLC.md +40 -40
- package/.agents/docs/configuration.md +16 -16
- package/.agents/docs/execution-reference.md +3 -3
- package/.agents/docs/quality-gates.md +2 -2
- package/.agents/docs/workflows.md +6 -6
- package/.agents/instructions.md +5 -5
- package/.agents/rules/changelog-style.md +3 -3
- package/.agents/rules/ci-remediation.md +1 -1
- package/.agents/rules/git-conventions-reference.md +4 -4
- package/.agents/schemas/agentrc.schema.json +9 -9
- package/.agents/schemas/story-deliver-terminal.schema.json +2 -2
- package/.agents/schemas/validation-evidence.schema.json +1 -1
- package/.agents/scripts/acceptance-eval.js +1 -1
- package/.agents/scripts/apply-quality-bootstrap.js +1 -1
- package/.agents/scripts/audit-to-stories.js +2 -2
- package/.agents/scripts/check-doc-links.js +32 -4
- package/.agents/scripts/check-test-temp-hygiene.js +1 -1
- package/.agents/scripts/check-workflow-cli-lint.js +1 -1
- package/.agents/scripts/deliver-light.js +10 -10
- package/.agents/scripts/deliver-recover.js +1 -1
- package/.agents/scripts/drain-pending-cleanup.js +1 -1
- package/.agents/scripts/evidence-gate.js +1 -1
- package/.agents/scripts/generate-workflows-doc.js +1 -1
- package/.agents/scripts/lib/audit-suite/selector.js +1 -1
- package/.agents/scripts/lib/audit-to-stories/audit-label-taxonomy.js +1 -1
- package/.agents/scripts/lib/audit-to-stories/build-story-body.js +1 -1
- package/.agents/scripts/lib/audit-to-stories/seed-from-findings.js +5 -5
- package/.agents/scripts/lib/audit-to-stories/wire-dependencies.js +1 -1
- package/.agents/scripts/lib/bdd-runner-detect.js +1 -1
- package/.agents/scripts/lib/bdd-scenario-budget.js +1 -1
- package/.agents/scripts/lib/bdd-scenario-scanner.js +3 -3
- package/.agents/scripts/lib/bdd-step-index.js +1 -1
- package/.agents/scripts/lib/bootstrap/branch-protection.js +1 -1
- package/.agents/scripts/lib/bootstrap/commit-push.js +2 -2
- package/.agents/scripts/lib/bootstrap/issue-forms-template.js +1 -1
- package/.agents/scripts/lib/checks/core-bare-clean.js +1 -1
- package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +1 -1
- package/.agents/scripts/lib/cli-args.js +1 -1
- package/.agents/scripts/lib/command-header.js +1 -1
- package/.agents/scripts/lib/config/delivery-routing.js +1 -1
- package/.agents/scripts/lib/config/explain.js +1 -1
- package/.agents/scripts/lib/config/runners.js +2 -2
- package/.agents/scripts/lib/config/runtime.js +1 -1
- package/.agents/scripts/lib/config/temp-paths.js +2 -2
- package/.agents/scripts/lib/config-settings-schema-delivery.js +3 -3
- package/.agents/scripts/lib/config-settings-schema-quality.js +6 -6
- package/.agents/scripts/lib/config-settings-schema.js +3 -3
- package/.agents/scripts/lib/duplicate-search.js +1 -1
- package/.agents/scripts/lib/feedback-loop/prior-feedback-fetcher.js +4 -4
- package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +1 -1
- package/.agents/scripts/lib/findings/classify-finding.js +1 -1
- package/.agents/scripts/lib/findings/promote-finding.js +12 -12
- package/.agents/scripts/lib/findings/route-finding.js +2 -2
- package/.agents/scripts/lib/generated/agentrc-validator.js +1 -1
- package/.agents/scripts/lib/git-branch-lifecycle.js +2 -2
- package/.agents/scripts/lib/label-constants.js +2 -2
- package/.agents/scripts/lib/label-taxonomy.js +1 -1
- package/.agents/scripts/lib/onboard/init-tail.js +4 -4
- package/.agents/scripts/lib/onboard/scaffold-docs.js +2 -2
- package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +1 -1
- package/.agents/scripts/lib/orchestration/code-review.js +4 -4
- package/.agents/scripts/lib/orchestration/complexity-gate.js +5 -5
- package/.agents/scripts/lib/orchestration/deliver-recover.js +3 -3
- package/.agents/scripts/lib/orchestration/docs-digest.js +3 -3
- package/.agents/scripts/lib/orchestration/lease-guard-shared.js +2 -2
- package/.agents/scripts/lib/orchestration/light-backstop.js +1 -1
- package/.agents/scripts/lib/orchestration/light-escalation.js +6 -6
- package/.agents/scripts/lib/orchestration/light-suitability.js +19 -19
- package/.agents/scripts/lib/orchestration/plan-context.js +4 -4
- package/.agents/scripts/lib/orchestration/plan-critic-conditions.js +2 -2
- package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +2 -2
- package/.agents/scripts/lib/orchestration/plan-metrics.js +1 -1
- package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +1 -1
- package/.agents/scripts/lib/orchestration/plan-persist/plan-context-source.js +3 -3
- package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +6 -6
- package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +16 -16
- package/.agents/scripts/lib/orchestration/plan-persist/summary.js +3 -3
- package/.agents/scripts/lib/orchestration/plan-persist/supersede-ops.js +6 -6
- package/.agents/scripts/lib/orchestration/planning/authoring-context.js +7 -7
- package/.agents/scripts/lib/orchestration/planning/decomposer-context.js +1 -1
- package/.agents/scripts/lib/orchestration/planning/memory-pool-advisory.js +3 -3
- package/.agents/scripts/lib/orchestration/remote-verifier.js +2 -2
- package/.agents/scripts/lib/orchestration/resolve-stories.js +4 -4
- package/.agents/scripts/lib/orchestration/run-epilogue.js +2 -2
- package/.agents/scripts/lib/orchestration/single-story-close/phases/base-sync.js +2 -2
- package/.agents/scripts/lib/orchestration/single-story-close/phases/conventional-subject.js +1 -1
- package/.agents/scripts/lib/orchestration/single-story-close/phases/normalize-pr-title.js +5 -1
- package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +1 -1
- package/.agents/scripts/lib/orchestration/single-story-close/phases/wrong-tree-guard.js +3 -3
- package/.agents/scripts/lib/orchestration/single-story-close/runner.js +2 -2
- package/.agents/scripts/lib/orchestration/single-story-lease-guard.js +1 -1
- package/.agents/scripts/lib/orchestration/story-deliver-terminal.js +14 -12
- package/.agents/scripts/lib/orchestration/ticket-validator.js +1 -1
- package/.agents/scripts/lib/orchestration/ticketing/reads.js +3 -3
- package/.agents/scripts/lib/plan-phase-cleanup.js +1 -1
- package/.agents/scripts/lib/signals/schema.js +1 -1
- package/.agents/scripts/lib/story-adjacency.js +2 -2
- package/.agents/scripts/lib/templates/decomposer-prompts.js +1 -1
- package/.agents/scripts/lib/ticket-body-sections.js +1 -1
- package/.agents/scripts/lib/util/concurrent-map.js +1 -1
- package/.agents/scripts/lib/util/parse-id-list.js +1 -1
- package/.agents/scripts/lib/wave-runner/live-probe.js +4 -4
- package/.agents/scripts/lib/wave-runner/ready-set.js +1 -1
- package/.agents/scripts/lib/workflow-closure.js +1 -1
- package/.agents/scripts/lib/worktree/lifecycle/pending-cleanup.js +2 -2
- package/.agents/scripts/lint-issue-body.js +3 -3
- package/.agents/scripts/plan-context.js +4 -4
- package/.agents/scripts/plan-critics.js +2 -2
- package/.agents/scripts/plan-persist.js +2 -2
- package/.agents/scripts/plan-run-epilogue.js +2 -2
- package/.agents/scripts/providers/github/board-add.js +1 -1
- package/.agents/scripts/providers/github/errors.js +1 -1
- package/.agents/scripts/providers/github/tickets.js +6 -6
- package/.agents/scripts/resolve-stories.js +3 -3
- package/.agents/scripts/resync-status-column.js +1 -1
- package/.agents/scripts/run-lint.js +1 -1
- package/.agents/scripts/single-story-close.js +2 -2
- package/.agents/scripts/single-story-init.js +5 -5
- package/.agents/scripts/stories-wave-tick.js +8 -8
- package/.agents/skills/core/idea-refinement/SKILL.md +5 -5
- package/.agents/skills/core/scope-triage/SKILL.md +3 -3
- package/.agents/skills/skills.index.json +1 -1
- package/.agents/skills/stack/qa/qa-harness/SKILL.md +1 -1
- package/.agents/workflows/audit-data-model.md +1 -1
- package/.agents/workflows/audit-documentation.md +2 -2
- package/.agents/workflows/audit-to-stories.md +11 -11
- package/.agents/workflows/git-deliver.md +4 -4
- package/.agents/workflows/helpers/_merge-conflict-template.md +1 -1
- package/.agents/workflows/helpers/audit-lens-core.md +1 -1
- package/.agents/workflows/helpers/code-review.md +4 -4
- package/.agents/workflows/helpers/deliver-light.md +26 -26
- package/.agents/workflows/helpers/deliver-reference.md +15 -7
- package/.agents/workflows/helpers/deliver-story-reference.md +9 -4
- package/.agents/workflows/helpers/deliver-story.md +6 -7
- package/.agents/workflows/helpers/diagnose.md +2 -2
- package/.agents/workflows/helpers/parallel-tooling.md +1 -1
- package/.agents/workflows/helpers/plan-reference.md +9 -9
- package/.agents/workflows/helpers/qa-core.md +8 -8
- package/.agents/workflows/helpers/worktree-lifecycle.md +6 -6
- package/.agents/workflows/{deliver.md → mandrel-deliver.md} +15 -19
- package/.agents/workflows/{plan.md → mandrel-plan.md} +9 -9
- package/.agents/workflows/memory-consolidate.md +4 -4
- package/.agents/workflows/prototype.md +3 -3
- package/.agents/workflows/qa-assist.md +12 -12
- package/.agents/workflows/qa-explore.md +6 -6
- package/.agents/workflows/qa-run.md +1 -1
- package/README.md +7 -7
- package/docs/CHANGELOG.md +11 -0
- package/lib/cli/doctor.js +1 -1
- package/lib/cli/init.js +1 -1
- package/lib/migrations/steps/2.2.0-retire-epic-ac-tags.js +1 -1
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* story-ops.js — flat Story creation for v2 plan-persist (Stage 3).
|
|
3
3
|
*
|
|
4
|
-
* Under the Story collapse (`docs/roadmap.md` § Stage 3), `/plan` persists
|
|
4
|
+
* Under the Story collapse (`docs/roadmap.md` § Stage 3), `/mandrel-plan` persists
|
|
5
5
|
* zero-or-more Story issues directly — no Epic parent, no reconciler tree,
|
|
6
6
|
* no `deliveryShape` mode matrix. Default is **one Story**; N>1 is gated by
|
|
7
7
|
* the Stage-1 split-policy validator (`assertAcceptancePartition`).
|
|
@@ -44,7 +44,7 @@ import {
|
|
|
44
44
|
*
|
|
45
45
|
* Reintroduced (Story #4692) after Story #4540 retired it: #4540 was right
|
|
46
46
|
* that batch identity is the wrong axis for *ordering delivery across runs*
|
|
47
|
-
* (`/deliver` takes ids and resolves the graph from live state — that stays),
|
|
47
|
+
* (`/mandrel-deliver` takes ids and resolves the graph from live state — that stays),
|
|
48
48
|
* but it is the correct axis for *grouping the Stories one plan run created*
|
|
49
49
|
* so a cohort is filterable and traceable in the GitHub UI. The label is
|
|
50
50
|
* metadata only; nothing in persist or delivery reads it as a
|
|
@@ -57,7 +57,7 @@ const PLAN_RUN_LABEL_COLOR = '#C5DEF5';
|
|
|
57
57
|
|
|
58
58
|
/**
|
|
59
59
|
* Stable color for the `route::lite` ceremony-route hint (Story #4707;
|
|
60
|
-
* hint-only since Story #4722 — `/deliver` re-derives the route from the
|
|
60
|
+
* hint-only since Story #4722 — `/mandrel-deliver` re-derives the route from the
|
|
61
61
|
* Story body's shape).
|
|
62
62
|
*/
|
|
63
63
|
const LITE_ROUTE_LABEL_COLOR = '#D4C5F9';
|
|
@@ -475,7 +475,7 @@ function assembleOnePlanStory(ticket, opts) {
|
|
|
475
475
|
const serialized = serializeStoryBody({ ...folded, depends_on });
|
|
476
476
|
// Carry audit dedup provenance into the persisted body (Story #4877). The
|
|
477
477
|
// audit sweep's Single-plan path stamps the `audit-fingerprints` /
|
|
478
|
-
// `audit-semantic-keys` footers into the seed it hands `/plan`; without this
|
|
478
|
+
// `audit-semantic-keys` footers into the seed it hands `/mandrel-plan`; without this
|
|
479
479
|
// the persisted Story carries no provenance and the next sweep re-files work
|
|
480
480
|
// it already planned. Mechanical on purpose — the authoring agent is not
|
|
481
481
|
// asked to notice HTML comments in a one-pager. A non-audit seed carries no
|
|
@@ -529,7 +529,7 @@ function assertSharedSpecAllowed(tickets, sharedSpec) {
|
|
|
529
529
|
* @param {object} [opts]
|
|
530
530
|
* @param {string|null} [opts.sharedSpec]
|
|
531
531
|
* @param {string[]} [opts.planAcceptance]
|
|
532
|
-
* @param {number[]} [opts.sourceTicketIds] Ids passed to `/plan --tickets`.
|
|
532
|
+
* @param {number[]} [opts.sourceTicketIds] Ids passed to `/mandrel-plan --tickets`.
|
|
533
533
|
* @returns {{ stories: Array<{ slug: string, title: string, body: string, acceptance: string[], depends_on: string[], supersedes: Array<{ id: number, note: string|null }> }> }}
|
|
534
534
|
*/
|
|
535
535
|
export function assemblePlanStories(tickets, opts = {}) {
|
|
@@ -756,14 +756,14 @@ function renderStoryBodyForCreate(story, idBySlug) {
|
|
|
756
756
|
*
|
|
757
757
|
* Ordering is authored as slugs and, until now, survived persist only as
|
|
758
758
|
* `blocked by #N` prose in the body footer. That footer stays — it is what
|
|
759
|
-
* `/deliver`'s resolver falls back on — but a native edge is the durable,
|
|
759
|
+
* `/mandrel-deliver`'s resolver falls back on — but a native edge is the durable,
|
|
760
760
|
* machine-readable form: visible in the GitHub UI, readable without parsing
|
|
761
761
|
* markdown, and settable by an operator later for cross-run order.
|
|
762
762
|
*
|
|
763
763
|
* **Non-fatal by design, and deliberately asymmetric with the read path.** A
|
|
764
764
|
* missing native edge is cosmetic here: `renderStoryBodyForCreate` has already
|
|
765
765
|
* written the footer, so ordering is not lost when the dependencies API says
|
|
766
|
-
* no. `/deliver`'s *read* of these edges is a real dispatch gate, which is why
|
|
766
|
+
* no. `/mandrel-deliver`'s *read* of these edges is a real dispatch gate, which is why
|
|
767
767
|
* that side fails loud. Persist reports the failure and completes.
|
|
768
768
|
*
|
|
769
769
|
* Two shape hazards this crossing has to get right, both silent if missed:
|
|
@@ -839,7 +839,7 @@ async function mirrorNativeDependencyEdges({ provider, stories, idBySlug }) {
|
|
|
839
839
|
*
|
|
840
840
|
* **Non-fatal by design**, matching the native-blocked_by mirroring posture:
|
|
841
841
|
* neither label is load-bearing for correctness (grouping is cosmetic, and
|
|
842
|
-
* the route label is a human-visible hint only — `/deliver` re-derives the
|
|
842
|
+
* the route label is a human-visible hint only — `/mandrel-deliver` re-derives the
|
|
843
843
|
* route from the Story body's shape, Story #4722), so it is never a reason
|
|
844
844
|
* to fail persist. On an ensure
|
|
845
845
|
* failure (throw, or the label reported `missing` by the post-loop
|
|
@@ -920,7 +920,7 @@ async function ensurePersistLabel({
|
|
|
920
920
|
* create — no relabel call is needed on the resume path, and the cohort is
|
|
921
921
|
* never split across two labels. The label is ensured to exist before the
|
|
922
922
|
* first POST, **non-fatally**: grouping is cosmetic and never fails the run
|
|
923
|
-
* (see `ensureCohortLabel`). `/deliver` never reads it — delivery stays
|
|
923
|
+
* (see `ensureCohortLabel`). `/mandrel-deliver` never reads it — delivery stays
|
|
924
924
|
* ids-only over live state (Story #4540's actual point).
|
|
925
925
|
*
|
|
926
926
|
* **The create loop stays serial and dependency-ordered** — deliberately, and
|
|
@@ -940,7 +940,7 @@ async function ensurePersistLabel({
|
|
|
940
940
|
* effective complexity route to `lite` (the planner's recorded verdict,
|
|
941
941
|
* upheld by the shape backstop), it passes the label via `opts.routeLabel`
|
|
942
942
|
* and every created Story carries it — a **human-visible hint only**, never
|
|
943
|
-
* the control signal: `/deliver` re-derives the route from each Story body's
|
|
943
|
+
* the control signal: `/mandrel-deliver` re-derives the route from each Story body's
|
|
944
944
|
* own shape (`resolveStoryDispatchMode`), so a lost or failed label write
|
|
945
945
|
* cannot misroute delivery. A full-routed plan passes nothing and its
|
|
946
946
|
* Stories carry **no** route label. Like the cohort label, the ensure is
|
|
@@ -1000,8 +1000,8 @@ export async function createStoryIssues({ provider, stories, opts = {} }) {
|
|
|
1000
1000
|
label: cohortLabel,
|
|
1001
1001
|
color: PLAN_RUN_LABEL_COLOR,
|
|
1002
1002
|
description:
|
|
1003
|
-
'Groups the Stories one /plan persist run authored (metadata ' +
|
|
1004
|
-
'only — /deliver stays ids-only).',
|
|
1003
|
+
'Groups the Stories one /mandrel-plan persist run authored (metadata ' +
|
|
1004
|
+
'only — /mandrel-deliver stays ids-only).',
|
|
1005
1005
|
role: 'cohort',
|
|
1006
1006
|
});
|
|
1007
1007
|
const applyRouteLabel =
|
|
@@ -1011,7 +1011,7 @@ export async function createStoryIssues({ provider, stories, opts = {} }) {
|
|
|
1011
1011
|
label: routeLabel,
|
|
1012
1012
|
color: LITE_ROUTE_LABEL_COLOR,
|
|
1013
1013
|
description:
|
|
1014
|
-
'Ceremony-lite hint (human-visible only): /deliver re-derives the ' +
|
|
1014
|
+
'Ceremony-lite hint (human-visible only): /mandrel-deliver re-derives the ' +
|
|
1015
1015
|
'route from the Story body shape; every close gate runs unchanged.',
|
|
1016
1016
|
role: 'route-marker',
|
|
1017
1017
|
}));
|
|
@@ -1101,9 +1101,9 @@ export async function createStoryIssues({ provider, stories, opts = {} }) {
|
|
|
1101
1101
|
*
|
|
1102
1102
|
* This is what makes `agent::ready` *mean* "fully persisted": by the time it
|
|
1103
1103
|
* lands, the Story's `story-plan-state` checkpoint is already on the ticket, so
|
|
1104
|
-
* a `/deliver` that picks it up cannot read a null checkpoint.
|
|
1104
|
+
* a `/mandrel-deliver` that picks it up cannot read a null checkpoint.
|
|
1105
1105
|
*
|
|
1106
|
-
* Fails closed: an un-flipped Story is invisible to `/deliver`, which is the
|
|
1106
|
+
* Fails closed: an un-flipped Story is invisible to `/mandrel-deliver`, which is the
|
|
1107
1107
|
* safe direction — the operator is told exactly which ids need the label.
|
|
1108
1108
|
*
|
|
1109
1109
|
* **Collect failures, never fast-fail** (preserved verbatim under the
|
|
@@ -1159,7 +1159,7 @@ export async function markStoriesReady({ provider, created }) {
|
|
|
1159
1159
|
`[plan-persist] ${failed.length} Story(ies) were created with their ` +
|
|
1160
1160
|
'checkpoints but could not be flipped to agent::ready:\n' +
|
|
1161
1161
|
`${failed.map((f) => ` - ${f}`).join('\n')}\n` +
|
|
1162
|
-
'They are invisible to /deliver until the label lands. Re-run persist ' +
|
|
1162
|
+
'They are invisible to /mandrel-deliver until the label lands. Re-run persist ' +
|
|
1163
1163
|
'(it resumes rather than duplicating) or add the label by hand.',
|
|
1164
1164
|
);
|
|
1165
1165
|
}
|
|
@@ -163,8 +163,8 @@ export function buildPlanSummaryCommentBody({
|
|
|
163
163
|
// must name real ids, not a batch token that no longer exists.
|
|
164
164
|
const deliverCommand =
|
|
165
165
|
Array.isArray(stories) && stories.length > 0
|
|
166
|
-
? `/deliver ${stories.map((s) => s.id).join(' ')}`
|
|
167
|
-
: '/deliver <storyId> [<storyId> ...]';
|
|
166
|
+
? `/mandrel-deliver ${stories.map((s) => s.id).join(' ')}`
|
|
167
|
+
: '/mandrel-deliver <storyId> [<storyId> ...]';
|
|
168
168
|
|
|
169
169
|
return [
|
|
170
170
|
`### 📋 Plan Summary — Story #${epicId} is \`agent::ready\``,
|
|
@@ -182,6 +182,6 @@ export function buildPlanSummaryCommentBody({
|
|
|
182
182
|
...renderWaveTableLines(waveTable),
|
|
183
183
|
...renderSharedEditorLines(conflictFindings),
|
|
184
184
|
'',
|
|
185
|
-
`_Deliver with \`${deliverCommand}\` — \`/deliver\` resolves the dependency graph from live state, so edges may point at Stories from earlier plan runs._`,
|
|
185
|
+
`_Deliver with \`${deliverCommand}\` — \`/mandrel-deliver\` resolves the dependency graph from live state, so edges may point at Stories from earlier plan runs._`,
|
|
186
186
|
].join('\n');
|
|
187
187
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* supersede-ops.js — close the `/plan --tickets` source issues that the
|
|
2
|
+
* supersede-ops.js — close the `/mandrel-plan --tickets` source issues that the
|
|
3
3
|
* authored Stories supersede (Story #4535).
|
|
4
4
|
*
|
|
5
5
|
* `plan-context.js` fetches the source issues, emits `sourceTickets[]` on the
|
|
6
|
-
* `/plan` envelope, and (with `--out`) writes that envelope to disk.
|
|
6
|
+
* `/mandrel-plan` envelope, and (with `--out`) writes that envelope to disk.
|
|
7
7
|
* `resolveSourceTicketIds` below reads the id set back off it, so the normal
|
|
8
|
-
* `/plan --tickets` path needs no flag; an explicit `--source-tickets` still
|
|
8
|
+
* `/mandrel-plan --tickets` path needs no flag; an explicit `--source-tickets` still
|
|
9
9
|
* wins when passed, as the override for hand-driven runs (Story #4554).
|
|
10
10
|
* Before that thread existed the ids reached
|
|
11
11
|
* this module *solely* via the hand-passed flag, so a forgotten flag left
|
|
@@ -187,7 +187,7 @@ function sameIdSet(a, b) {
|
|
|
187
187
|
* loudly (the operator is overriding what the run actually fetched)
|
|
188
188
|
* but honoured.
|
|
189
189
|
* 2. otherwise the envelope's `sourceTickets[]` — so the common
|
|
190
|
-
* `/plan --tickets` path needs no flag at all.
|
|
190
|
+
* `/mandrel-plan --tickets` path needs no flag at all.
|
|
191
191
|
* 3. otherwise empty, reported as `origin: 'none'`.
|
|
192
192
|
*
|
|
193
193
|
* `origin` is surfaced on the persist envelope so a run that superseded
|
|
@@ -240,7 +240,7 @@ function describeStoryIds(entries) {
|
|
|
240
240
|
* live against an inconsistent tracker.
|
|
241
241
|
*
|
|
242
242
|
* @param {Array<{ slug: string, supersedes: Array<{ id: number }> }>} stories
|
|
243
|
-
* @param {number[]} sourceTicketIds Ids passed to `/plan --tickets`.
|
|
243
|
+
* @param {number[]} sourceTicketIds Ids passed to `/mandrel-plan --tickets`.
|
|
244
244
|
*/
|
|
245
245
|
export function assertSupersedePartition(stories, sourceTicketIds = []) {
|
|
246
246
|
const list = Array.isArray(stories) ? stories : [];
|
|
@@ -313,7 +313,7 @@ export function buildSupersedeCommentBody({
|
|
|
313
313
|
const lines = [
|
|
314
314
|
`**Superseded by #${story.id}** — *${story.title}* (${labels.join(', ')}).`,
|
|
315
315
|
'',
|
|
316
|
-
`Planned via \`/plan --tickets ${sourceTicketIds.join(',')}\`.`,
|
|
316
|
+
`Planned via \`/mandrel-plan --tickets ${sourceTicketIds.join(',')}\`.`,
|
|
317
317
|
];
|
|
318
318
|
if (note) {
|
|
319
319
|
lines.push('', note);
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* phases/authoring-context.js — emit-context phase.
|
|
3
3
|
*
|
|
4
4
|
* Builds the authoring context the host LLM (or the
|
|
5
|
-
* `/plan` author step) needs to write the Tech Spec.
|
|
5
|
+
* `/mandrel-plan` author step) needs to write the Tech Spec.
|
|
6
6
|
* Returns a plain JSON-serialisable object; never hits the network beyond
|
|
7
7
|
* the provider call needed to load the Epic.
|
|
8
8
|
*/
|
|
@@ -31,12 +31,12 @@ import { buildMemoryPoolAdvisory } from './memory-pool-advisory.js';
|
|
|
31
31
|
* pull-on-demand, mirroring the Story #4324 delivery-children cutover).
|
|
32
32
|
*
|
|
33
33
|
* Ensures a docs digest exists at the **same** per-Epic temp path the
|
|
34
|
-
* `/deliver` story sub-agents already consume
|
|
34
|
+
* `/mandrel-deliver` story sub-agents already consume
|
|
35
35
|
* (`<tempRoot>/epic-<seedIssueId>/docs-digest.md`) via the shared
|
|
36
36
|
* `ensureDocsDigest` export in `docs-digest.js` — one generator, one file,
|
|
37
37
|
* reused across the planning and delivery surfaces for the same Epic. The
|
|
38
38
|
* envelope carries only the digest path, not embedded doc content; the
|
|
39
|
-
* planner (host LLM driving the `/plan` author step) reads the digest
|
|
39
|
+
* planner (host LLM driving the `/mandrel-plan` author step) reads the digest
|
|
40
40
|
* and pulls a full file/section on demand when it bears on the decision.
|
|
41
41
|
*
|
|
42
42
|
* Returns `null` — a silent no-op — when `project.docsContextFiles` is not
|
|
@@ -80,7 +80,7 @@ async function buildPlanningDocsContext({ seedIssueId, settings, cwd }) {
|
|
|
80
80
|
* Story #4977 — the scan itself stays uncapped (a faithful `.feature`
|
|
81
81
|
* index), but the envelope-bound result is truncated to
|
|
82
82
|
* `BDD_SCENARIOS_BYTE_BUDGET` via `capBddScenarios` so a mature Gherkin
|
|
83
|
-
* corpus cannot alone consume the `/plan` context-envelope ceiling. Callers
|
|
83
|
+
* corpus cannot alone consume the `/mandrel-plan` context-envelope ceiling. Callers
|
|
84
84
|
* needing the raw count read `totalScenarios` vs `includedScenarios`.
|
|
85
85
|
*
|
|
86
86
|
* @returns {ReturnType<typeof capBddScenarios>}
|
|
@@ -97,7 +97,7 @@ function scanBddScenariosBestEffort() {
|
|
|
97
97
|
|
|
98
98
|
/**
|
|
99
99
|
* Build the authoring context the host LLM (or the
|
|
100
|
-
* `/plan` author step) needs to write the Tech Spec.
|
|
100
|
+
* `/mandrel-plan` author step) needs to write the Tech Spec.
|
|
101
101
|
*
|
|
102
102
|
* `docsContext` is digest-first (Story #4433): a pointer at the per-Epic
|
|
103
103
|
* docs digest rather than embedded doc content, `null` when
|
|
@@ -133,7 +133,7 @@ export async function buildAuthoringContext(
|
|
|
133
133
|
const githubCfg = opts.github ?? null;
|
|
134
134
|
|
|
135
135
|
// Story #4952 — these five gathers share no data, so they run under bounded
|
|
136
|
-
// concurrency instead of five sequential awaits on the interactive `/plan`
|
|
136
|
+
// concurrency instead of five sequential awaits on the interactive `/mandrel-plan`
|
|
137
137
|
// path. `concurrentMap` preserves input order, so the destructuring is
|
|
138
138
|
// positional and the produced context is identical to the serial build:
|
|
139
139
|
//
|
|
@@ -149,7 +149,7 @@ export async function buildAuthoringContext(
|
|
|
149
149
|
// memory corpus is delivery retrospectives whose subject IS a delivered
|
|
150
150
|
// Story — and its directory (`~/.claude/projects/<repo>/memory/`) never
|
|
151
151
|
// resolved, because harness project dirs are cwd-slugs. This renders no
|
|
152
|
-
// per-entry verdict at all: it stats and counts, and the `/plan` spine
|
|
152
|
+
// per-entry verdict at all: it stats and counts, and the `/mandrel-plan` spine
|
|
153
153
|
// surfaces `recommend` at Gate #1. Filesystem-only and total;
|
|
154
154
|
// 5. Story #2554 — open meta feedback issues, so retro signals are routed
|
|
155
155
|
// into durable substrates rather than lost in chat. Best-effort:
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* memory-pool-advisory.js — the `/plan` Phase 0 memory-hygiene advisory.
|
|
2
|
+
* memory-pool-advisory.js — the `/mandrel-plan` Phase 0 memory-hygiene advisory.
|
|
3
3
|
*
|
|
4
4
|
* Replaces the retired memory-freshness pre-flight (Story #2557 / #4414) in
|
|
5
5
|
* the same slot, fixing both of that design's defects:
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* replaced by `-` — so the old path never resolved in any consumer and
|
|
11
11
|
* the scan was a silent no-op everywhere.
|
|
12
12
|
* 2. **A named consumer.** The retired scanner emitted a per-entry staleness
|
|
13
|
-
* verdict nothing read. This emits one advisory the `/plan` spine
|
|
13
|
+
* verdict nothing read. This emits one advisory the `/mandrel-plan` spine
|
|
14
14
|
* surfaces at Gate #1, recommending `/memory-consolidate`.
|
|
15
15
|
*
|
|
16
16
|
* It also drops the semantic that made the old scanner unfixable: it renders
|
|
@@ -131,7 +131,7 @@ function countEntries({ poolDir, fsImpl }) {
|
|
|
131
131
|
* Build the `memoryPoolAdvisory` envelope field.
|
|
132
132
|
*
|
|
133
133
|
* Advisory only — it carries **no routing authority**, mirroring
|
|
134
|
-
* `deliverLightSuggestion`. The `/plan` spine surfaces `recommend` at Gate #1;
|
|
134
|
+
* `deliverLightSuggestion`. The `/mandrel-plan` spine surfaces `recommend` at Gate #1;
|
|
135
135
|
* nothing auto-runs, and nothing here mutates the operator's memory store.
|
|
136
136
|
*
|
|
137
137
|
* @param {object} [opts]
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
* remote-verifier.js — deterministic "is there a live, pushable remote?"
|
|
4
4
|
* evidence for the delivery entry seams. Issue #4483.
|
|
5
5
|
*
|
|
6
|
-
* `/deliver` could silently shortcut the entire orchestration — building
|
|
6
|
+
* `/mandrel-deliver` could silently shortcut the entire orchestration — building
|
|
7
7
|
* the delivery inline and committing to local `main` without pushing —
|
|
8
8
|
* when the driving agent *perceived* the environment had no live GitHub
|
|
9
9
|
* remote. The judgment was vibes, not fact. This module gives the entry
|
|
10
|
-
* seams (`single-story-init.js` for v2 `/deliver`) a verified
|
|
10
|
+
* seams (`single-story-init.js` for v2 `/mandrel-deliver`) a verified
|
|
11
11
|
* probe result to record in their envelopes so the workflow can branch on
|
|
12
12
|
* `remoteVerified: true|false` deterministically: use the remote, or
|
|
13
13
|
* transition to `agent::blocked` quoting the probe output — never a
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* lib/orchestration/resolve-stories.js — resolve a set of Story ids into the
|
|
3
3
|
* `{ stories, dag, done }` envelope the delivery scheduler consumes.
|
|
4
4
|
*
|
|
5
|
-
* This is the ONE resolution step for `/deliver`. It generalizes the
|
|
5
|
+
* This is the ONE resolution step for `/mandrel-deliver`. It generalizes the
|
|
6
6
|
* envelope shaping proven by the retired `resolve-plan-run.js` and fixes the
|
|
7
7
|
* two defects that shipped with it:
|
|
8
8
|
*
|
|
@@ -77,7 +77,7 @@ export function toStoryRecord(issue, requestedId) {
|
|
|
77
77
|
if (!labels.includes(TYPE_LABELS.STORY)) {
|
|
78
78
|
throw new Error(
|
|
79
79
|
`[resolve-stories] Issue #${id} is not a Story (labels: ${labels.join(', ') || 'none'}). ` +
|
|
80
|
-
`/deliver accepts ${TYPE_LABELS.STORY} tickets only — close it or re-plan it as a v2 Story.`,
|
|
80
|
+
`/mandrel-deliver accepts ${TYPE_LABELS.STORY} tickets only — close it or re-plan it as a v2 Story.`,
|
|
81
81
|
);
|
|
82
82
|
}
|
|
83
83
|
const body = String(issue?.body ?? '');
|
|
@@ -351,7 +351,7 @@ export function buildStoriesEnvelope({
|
|
|
351
351
|
return {
|
|
352
352
|
kind: 'stories',
|
|
353
353
|
// `dispatchMode` (Story #4722, #4736, #4829): the resolver reports the
|
|
354
|
-
// per-Story execution mode so `/deliver` reads one field — `inline` (run
|
|
354
|
+
// per-Story execution mode so `/mandrel-deliver` reads one field — `inline` (run
|
|
355
355
|
// deliver-story in the router's own session: no story-worker /
|
|
356
356
|
// acceptance-critic sub-agent boots) or `subagent` (the conservative
|
|
357
357
|
// default). Model-side fan-out only; close gates are untouched.
|
|
@@ -385,7 +385,7 @@ export function buildStoriesEnvelope({
|
|
|
385
385
|
/**
|
|
386
386
|
* Parse and validate the `--ids` list, expanding any `A-B` dash range.
|
|
387
387
|
*
|
|
388
|
-
* A contiguous span is how an operator names a plan run — `/deliver 4922 -
|
|
388
|
+
* A contiguous span is how an operator names a plan run — `/mandrel-deliver 4922 -
|
|
389
389
|
* 4926` — so the range is expanded here rather than transcribed by the host.
|
|
390
390
|
* `stories-wave-tick.js --stories` reads through this same function, which is
|
|
391
391
|
* what keeps the sequencing set identical to the resolved one.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* run-epilogue.js — real per-run closeout for `/deliver --run`.
|
|
2
|
+
* run-epilogue.js — real per-run closeout for `/mandrel-deliver --run`.
|
|
3
3
|
*
|
|
4
4
|
* After the last Story in a multi-Story plan-run lands, this module:
|
|
5
5
|
* 1. Selects the cross-Story audit lens roster over the combined landed
|
|
@@ -100,7 +100,7 @@ export function planRunEpilogue({ planRunId, stories } = {}) {
|
|
|
100
100
|
};
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
// Positional `/deliver 101 102` has no plan-run label. Synthesize a
|
|
103
|
+
// Positional `/mandrel-deliver 101 102` has no plan-run label. Synthesize a
|
|
104
104
|
// stable adhoc id from the sorted Story set so the epilogue still
|
|
105
105
|
// anchors comments / audit roster without requiring `--run`.
|
|
106
106
|
const effectiveRunId =
|
|
@@ -83,7 +83,7 @@ export async function runBaseSyncPhase({
|
|
|
83
83
|
: syncResult.stderr
|
|
84
84
|
? `: ${syncResult.stderr.slice(0, 200)}`
|
|
85
85
|
: '') +
|
|
86
|
-
`. Story transitioned to ${AGENT_LABELS.BLOCKED}; resolve in ${syncCwd} and re-run \`/deliver ${storyId}\`.`,
|
|
86
|
+
`. Story transitioned to ${AGENT_LABELS.BLOCKED}; resolve in ${syncCwd} and re-run \`/mandrel-deliver ${storyId}\`.`,
|
|
87
87
|
);
|
|
88
88
|
}
|
|
89
89
|
progress('SYNC', `✅ Synced from origin/${baseBranch} (${syncResult.kind}).`);
|
|
@@ -182,7 +182,7 @@ export function buildSyncFailureCommentBody({
|
|
|
182
182
|
const lines = [
|
|
183
183
|
`### ${heading}`,
|
|
184
184
|
'',
|
|
185
|
-
'`/deliver` close-validation passed, but the pre-push',
|
|
185
|
+
'`/mandrel-deliver` close-validation passed, but the pre-push',
|
|
186
186
|
`sync against \`origin/${baseBranch}\` could not complete. The Story has`,
|
|
187
187
|
`been transitioned to \`agent::blocked\`. To resume:`,
|
|
188
188
|
'',
|
|
@@ -343,7 +343,7 @@ function scanForBreaking(text, readHeaderBang) {
|
|
|
343
343
|
* writing the commit that does the breaking.
|
|
344
344
|
* - **The Story body** — the same footer, written as its own line anywhere
|
|
345
345
|
* in the Story issue (the `## Spec` block is the natural home). This is
|
|
346
|
-
* the declarative path: `/plan` can state the break up front and close
|
|
346
|
+
* the declarative path: `/mandrel-plan` can state the break up front and close
|
|
347
347
|
* propagates it even when no individual commit remembered the footer.
|
|
348
348
|
* Only the footer form counts; prose describing a break does not, because
|
|
349
349
|
* a keyword-free sentence is exactly what release-please cannot parse.
|
|
@@ -191,7 +191,11 @@ function synthesizeSubject({ description, storyId, commitMessages }) {
|
|
|
191
191
|
* @returns {string}
|
|
192
192
|
*/
|
|
193
193
|
function buildPrBody({ storyId, breakingNotes }) {
|
|
194
|
-
const lines = [
|
|
194
|
+
const lines = [
|
|
195
|
+
`Closes #${storyId}`,
|
|
196
|
+
'',
|
|
197
|
+
'_Auto-opened by `/mandrel-deliver`._',
|
|
198
|
+
];
|
|
195
199
|
if (breakingNotes.length > 0) {
|
|
196
200
|
lines.push('', `BREAKING CHANGE: ${breakingNotes.join(' ')}`);
|
|
197
201
|
}
|
|
@@ -19,7 +19,7 @@ export async function handleCriticalReviewBlock({
|
|
|
19
19
|
'### Code review blocked delivery',
|
|
20
20
|
'',
|
|
21
21
|
`The Story-scope review reported **${criticalCount} critical blocker(s)** on ${prUrl}.`,
|
|
22
|
-
'Remediate the posted findings, then re-run `/deliver`.',
|
|
22
|
+
'Remediate the posted findings, then re-run `/mandrel-deliver`.',
|
|
23
23
|
'',
|
|
24
24
|
'If you have reviewed a finding and judged it wrong, re-run close with',
|
|
25
25
|
'`--override-review-block "<reason>"` rather than merging by hand — see',
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* phases/wrong-tree-guard.js — detect worktree/main-checkout edit divergence.
|
|
3
3
|
*
|
|
4
|
-
* Story #3364 — `/single-story-deliver` (and `/deliver`) materializes a
|
|
4
|
+
* Story #3364 — `/single-story-deliver` (and `/mandrel-deliver`) materializes a
|
|
5
5
|
* per-Story worktree and instructs the agent to `cd` into it before editing.
|
|
6
6
|
* On Windows that guidance is silently insufficient: `cd <workCwd>` steers the
|
|
7
7
|
* Bash tool's working directory, but the path-based Edit/Write tools operate on
|
|
@@ -232,7 +232,7 @@ export function formatWrongTreeFinding({ storyId, strayFiles, worktreePath }) {
|
|
|
232
232
|
`**Recovery:** relocate these edits into the worktree (re-apply them under ` +
|
|
233
233
|
`\`${worktreePath}\`), restore the main checkout ` +
|
|
234
234
|
`(\`git -C <main-repo> checkout -- <files>\`), then re-run ` +
|
|
235
|
-
`\`/deliver ${storyId}\`.`
|
|
235
|
+
`\`/mandrel-deliver ${storyId}\`.`
|
|
236
236
|
);
|
|
237
237
|
}
|
|
238
238
|
|
|
@@ -307,7 +307,7 @@ async function abortWrongTree({
|
|
|
307
307
|
`diff-path set while the worktree (${worktreePath}) is the active work ` +
|
|
308
308
|
`tree. Close aborted to avoid an empty-diff PR. Stray files: ` +
|
|
309
309
|
`${strayFiles.join(', ')}. Relocate the edits into the worktree, ` +
|
|
310
|
-
`restore the main checkout, then re-run /deliver ${storyId}.`,
|
|
310
|
+
`restore the main checkout, then re-run /mandrel-deliver ${storyId}.`,
|
|
311
311
|
);
|
|
312
312
|
}
|
|
313
313
|
|
|
@@ -84,7 +84,7 @@ async function emitTerminal({ terminal, result, config }) {
|
|
|
84
84
|
* issue as `completed` (the `Closes #<id>` footer firing on merge — the work
|
|
85
85
|
* IS on the base branch) or as `not_planned` (superseded by a re-plan,
|
|
86
86
|
* abandoned — nothing ever merged). Reporting the second as `landed` told
|
|
87
|
-
* `/deliver` that work had reached `main` when no PR ever merged, which would
|
|
87
|
+
* `/mandrel-deliver` that work had reached `main` when no PR ever merged, which would
|
|
88
88
|
* also satisfy any dependent Story waiting on it. Fail loudly instead: being
|
|
89
89
|
* handed an abandoned Story is an input error only the operator can resolve.
|
|
90
90
|
*
|
|
@@ -283,7 +283,7 @@ async function openAndReviewPr({
|
|
|
283
283
|
});
|
|
284
284
|
throw new Error(
|
|
285
285
|
`[single-story-close] Story-scope review reported ${criticalCount} critical blocker(s) on PR ${prUrl}. ` +
|
|
286
|
-
'Auto-merge was not enabled. Remediate the findings posted to the PR and re-run `/deliver`. ' +
|
|
286
|
+
'Auto-merge was not enabled. Remediate the findings posted to the PR and re-run `/mandrel-deliver`. ' +
|
|
287
287
|
'If you have reviewed a finding and judged it wrong, re-run with ' +
|
|
288
288
|
'`--override-review-block "<reason>"` rather than merging by hand.',
|
|
289
289
|
);
|
|
@@ -105,7 +105,7 @@ export async function acquireStoryLease({
|
|
|
105
105
|
steal,
|
|
106
106
|
renderRefusal: (result) =>
|
|
107
107
|
`single-story lease: Story #${storyId} is currently held by @${result.owner}. ` +
|
|
108
|
-
'Another /deliver run owns this Story. Coordinate with that ' +
|
|
108
|
+
'Another /mandrel-deliver run owns this Story. Coordinate with that ' +
|
|
109
109
|
'operator, or re-run with --steal to forcibly transfer the claim once you ' +
|
|
110
110
|
'have confirmed the other run is dead. (A foreign assignee always ' +
|
|
111
111
|
'blocks unless stolen.)',
|
|
@@ -47,7 +47,7 @@ export const TERMINAL_ENVELOPE_KIND = 'story-deliver-terminal';
|
|
|
47
47
|
* `pending` is **3**, not 0 and not 1. Zero would tell a headless caller the
|
|
48
48
|
* Story landed when it did not; one would conflate a resumable slow-CI wait
|
|
49
49
|
* with a hard block and send the operator to diagnose branch protection that
|
|
50
|
-
* is working fine. A distinct code is what lets `/deliver` resume without
|
|
50
|
+
* is working fine. A distinct code is what lets `/mandrel-deliver` resume without
|
|
51
51
|
* classifying.
|
|
52
52
|
*/
|
|
53
53
|
export const TERMINAL_EXIT_CODES = Object.freeze({
|
|
@@ -61,7 +61,7 @@ export const TERMINAL_EXIT_CODES = Object.freeze({
|
|
|
61
61
|
* terminal, not a new one, so giving it a fresh code would fork a vocabulary
|
|
62
62
|
* callers already branch on. It stays distinct from `landed` (nothing was
|
|
63
63
|
* delivered) and from `blocked`/`failed` (nothing is wrong — the work simply
|
|
64
|
-
* belongs to `/plan`).
|
|
64
|
+
* belongs to `/mandrel-plan`).
|
|
65
65
|
*/
|
|
66
66
|
escalated: 2,
|
|
67
67
|
});
|
|
@@ -74,12 +74,12 @@ export const TERMINAL_STATUSES = Object.freeze([
|
|
|
74
74
|
'escalated',
|
|
75
75
|
]);
|
|
76
76
|
|
|
77
|
-
/** Cap on the prompt echoed into an escalation's `/plan` next command. */
|
|
77
|
+
/** Cap on the prompt echoed into an escalation's `/mandrel-plan` next command. */
|
|
78
78
|
const PLAN_PROMPT_MAX = 200;
|
|
79
79
|
|
|
80
80
|
/**
|
|
81
81
|
* Render an operator prompt safe to sit inside the double quotes of the
|
|
82
|
-
* `/plan "<prompt>"` next command: collapse newlines (a next command is one
|
|
82
|
+
* `/mandrel-plan "<prompt>"` next command: collapse newlines (a next command is one
|
|
83
83
|
* line by contract), escape backslashes and double quotes so the quoting
|
|
84
84
|
* cannot be broken out of, and cap the length so a long prompt does not turn
|
|
85
85
|
* the envelope into a transcript. Total — a non-string yields the empty
|
|
@@ -133,7 +133,7 @@ export const NEXT_COMMANDS = Object.freeze({
|
|
|
133
133
|
recover: (storyId) =>
|
|
134
134
|
`node .agents/scripts/deliver-recover.js --story ${storyId}`,
|
|
135
135
|
/**
|
|
136
|
-
* Hand over-scope work to `/plan` — the next command of an `escalated`
|
|
136
|
+
* Hand over-scope work to `/mandrel-plan` — the next command of an `escalated`
|
|
137
137
|
* terminal (Story #4746).
|
|
138
138
|
*
|
|
139
139
|
* The only entry here that is a slash command rather than a script, and
|
|
@@ -143,7 +143,7 @@ export const NEXT_COMMANDS = Object.freeze({
|
|
|
143
143
|
* the workflow's escalation section for why running it in the escalating
|
|
144
144
|
* session is forbidden.
|
|
145
145
|
*/
|
|
146
|
-
escalateToPlan: (prompt) => `/plan "${quoteForPlan(prompt)}"`,
|
|
146
|
+
escalateToPlan: (prompt) => `/mandrel-plan "${quoteForPlan(prompt)}"`,
|
|
147
147
|
});
|
|
148
148
|
|
|
149
149
|
/**
|
|
@@ -260,15 +260,15 @@ export function buildTerminalEnvelope({
|
|
|
260
260
|
* `/deliver-light`'s suitability gate already decided correctly when it
|
|
261
261
|
* overrode a `lite` self-verdict on shape; what it lacked was an outcome a
|
|
262
262
|
* session could not walk past. A mandrel-bench 2.13.0 light-arm run did
|
|
263
|
-
* exactly that — it read the gate's `escalate-plan`, then invoked `/plan`
|
|
263
|
+
* exactly that — it read the gate's `escalate-plan`, then invoked `/mandrel-plan`
|
|
264
264
|
* in the same session and delivered. The continuation was not harmless:
|
|
265
265
|
* planning inside a session already framed as small work authored ONE Story
|
|
266
|
-
* against the scenario's 3-5 contract, where a fresh `/plan` session on the
|
|
266
|
+
* against the scenario's 3-5 contract, where a fresh `/mandrel-plan` session on the
|
|
267
267
|
* identical seed authored four. Escalation silently produced the very
|
|
268
268
|
* under-decomposition the guard exists to prevent.
|
|
269
269
|
*
|
|
270
270
|
* So the outcome is a validated envelope with its own exit code, naming the
|
|
271
|
-
* `/plan` command that owns the work, and asserting per artifact that nothing
|
|
271
|
+
* `/mandrel-plan` command that owns the work, and asserting per artifact that nothing
|
|
272
272
|
* was started. Every guarantee here is enforced by the schema rather than by
|
|
273
273
|
* prose: `storyId` must be null, `escalation.created.*` are pinned `false`.
|
|
274
274
|
*
|
|
@@ -288,10 +288,10 @@ export function buildEscalationTerminal({
|
|
|
288
288
|
}) {
|
|
289
289
|
const quoted = quoteForPlan(prompt);
|
|
290
290
|
if (quoted === '') {
|
|
291
|
-
// An escalation whose next command is `/plan ""` hands the operator
|
|
291
|
+
// An escalation whose next command is `/mandrel-plan ""` hands the operator
|
|
292
292
|
// nothing — the same walk-past-able non-outcome in envelope clothing.
|
|
293
293
|
throw new TypeError(
|
|
294
|
-
'buildEscalationTerminal: a non-empty prompt is required — the escalated terminal exists to name the /plan invocation that owns the work',
|
|
294
|
+
'buildEscalationTerminal: a non-empty prompt is required — the escalated terminal exists to name the /mandrel-plan invocation that owns the work',
|
|
295
295
|
);
|
|
296
296
|
}
|
|
297
297
|
const recorded = (Array.isArray(reasons) ? reasons : []).filter(
|
|
@@ -305,7 +305,9 @@ export function buildEscalationTerminal({
|
|
|
305
305
|
reasons:
|
|
306
306
|
recorded.length > 0
|
|
307
307
|
? recorded
|
|
308
|
-
: [
|
|
308
|
+
: [
|
|
309
|
+
'predicted scope exceeds the light ceilings — escalate to /mandrel-plan',
|
|
310
|
+
],
|
|
309
311
|
// Not computed from anything: the escalation path returns before the
|
|
310
312
|
// receipt/init call sites, so these are the assertion that it did.
|
|
311
313
|
created: { receiptStory: false, storyBranch: false, worktree: false },
|
|
@@ -421,7 +421,7 @@ function renderMissLine({ slug, path }) {
|
|
|
421
421
|
* The returned tickets array carries two extra non-array properties:
|
|
422
422
|
* - `findings` — structured sizing findings (hard + soft) keyed by the
|
|
423
423
|
* three-layer sizing model. The bounded re-decomposition loop in
|
|
424
|
-
* `/plan` reads `findings.filter(f => f.severity === 'hard')` to decide
|
|
424
|
+
* `/mandrel-plan` reads `findings.filter(f => f.severity === 'hard')` to decide
|
|
425
425
|
* whether to re-prompt.
|
|
426
426
|
* - `errors` — human-readable strings, one per hard finding. Non-empty
|
|
427
427
|
* `errors[]` is the AC-visible "block normalization" signal; the legacy
|
|
@@ -120,7 +120,7 @@ export const STRUCTURED_COMMENT_TYPES = Object.freeze([
|
|
|
120
120
|
'epic-handoff',
|
|
121
121
|
// Story #2899 (Epic #2880, F13) — the deleted `epic-deliver-preflight.js`
|
|
122
122
|
// upserted a `delivery-preflight` comment on the Epic at the start of
|
|
123
|
-
// pre-v2 Epic `/deliver` Phase 1, surfacing estimated story count, install cost,
|
|
123
|
+
// pre-v2 Epic `/mandrel-deliver` Phase 1, surfacing estimated story count, install cost,
|
|
124
124
|
// wave count, GitHub API request volume, Claude quota burn, and any
|
|
125
125
|
// threshold breaches against `delivery.preflight.max*`. One entry per
|
|
126
126
|
// Epic; re-runs replace prior content.
|
|
@@ -131,7 +131,7 @@ export const STRUCTURED_COMMENT_TYPES = Object.freeze([
|
|
|
131
131
|
// `close-validate.end`. One entry per Epic; re-ticks with the same
|
|
132
132
|
// findings upsert in place (`upsertStructuredComment` diffs by body).
|
|
133
133
|
'recurring-failure-class',
|
|
134
|
-
// Story #3061 (Epic #3051) — the pre-v2 `/deliver` idle-watchdog prose
|
|
134
|
+
// Story #3061 (Epic #3051) — the pre-v2 `/mandrel-deliver` idle-watchdog prose
|
|
135
135
|
// instructed the parent host LLM to upsert a `wave-stall` comment on the
|
|
136
136
|
// Epic whenever an in-flight Story had been silent for longer than the
|
|
137
137
|
// configured cadence. The deleted `wave-tick.js --check-idle` CLI emitted
|
|
@@ -166,7 +166,7 @@ export const STRUCTURED_COMMENT_TYPES = Object.freeze([
|
|
|
166
166
|
// (replaces epic-plan-state for new plans). plan-summary stays primary-only.
|
|
167
167
|
'story-plan-state',
|
|
168
168
|
// Story #4535 — `plan-persist.js` upserts a `superseded-by` comment on
|
|
169
|
-
// each `/plan --tickets` source issue at persist time, naming the single
|
|
169
|
+
// each `/mandrel-plan --tickets` source issue at persist time, naming the single
|
|
170
170
|
// Story that claims it (plus any per-supersede note the plan authored),
|
|
171
171
|
// immediately before closing the issue as `not_planned`. Keying off this
|
|
172
172
|
// marker rather than a bare `postComment` is what makes a re-run
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* plan-phase-cleanup.js — Post-phase temp-file cleanup for `/plan`.
|
|
2
|
+
* plan-phase-cleanup.js — Post-phase temp-file cleanup for `/mandrel-plan`.
|
|
3
3
|
*
|
|
4
4
|
* The spec and decompose phases write several run-scoped temp files under
|
|
5
5
|
* the per-run tree (`temp/run-<id>/planner-context.json`,
|
|
@@ -91,7 +91,7 @@ export const EVENT_KINDS = Object.freeze({
|
|
|
91
91
|
// Story #3819 — per-criterion acceptance self-eval signal emitted by
|
|
92
92
|
// acceptance-eval.js. One record per Story per eval-loop terminus,
|
|
93
93
|
// carrying which acceptance items needed rework and the round count, so
|
|
94
|
-
// the retro and /plan Phase 0 feedback fetch can see acceptance
|
|
94
|
+
// the retro and /mandrel-plan Phase 0 feedback fetch can see acceptance
|
|
95
95
|
// churn alongside friction/hotspot data.
|
|
96
96
|
ACCEPTANCE_EVAL: 'acceptance-eval',
|
|
97
97
|
// Forensic breadcrumb appended to the per-Epic stream by the notify
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* lib/story-adjacency.js — the single story-level adjacency builder.
|
|
3
3
|
*
|
|
4
|
-
* Both pre-v2 Epic wave wrappers and the v2 `/deliver` ready-set path bottom out in the shared
|
|
4
|
+
* Both pre-v2 Epic wave wrappers and the v2 `/mandrel-deliver` ready-set path bottom out in the shared
|
|
5
5
|
* `lib/Graph.js` kernel (`detectCycle` / `assignLayers` / `computeWaves`),
|
|
6
6
|
* but each historically re-implemented the step that turns a list of Story
|
|
7
7
|
* records into the `Map<storyId, number[]>` adjacency the kernel consumes.
|
|
@@ -43,7 +43,7 @@ import { parseBlockedBy } from './dependency-parser.js';
|
|
|
43
43
|
* DAG nodes).
|
|
44
44
|
* @param {object} [opts]
|
|
45
45
|
* @param {boolean} [opts.dropForeign=false] When `false` (the v2 default,
|
|
46
|
-
* matching the `/deliver` path — `stories-wave-tick.js` and the
|
|
46
|
+
* matching the `/mandrel-deliver` path — `stories-wave-tick.js` and the
|
|
47
47
|
* `planReadySet` core), the operator-DAG contract is preserved: a
|
|
48
48
|
* dependency on an id absent from the input is treated as not-yet-done
|
|
49
49
|
* and withholds the dependent until it completes. When `true` (the
|
|
@@ -21,7 +21,7 @@ import { BODY_FORMAT_LINTS } from '../story-body/body-format-lints.js';
|
|
|
21
21
|
*
|
|
22
22
|
* **Single source of the prompt body (Story #4162).** This module is the sole
|
|
23
23
|
* carrier of the full decomposer system-prompt body, delivered to the host
|
|
24
|
-
* LLM in the `systemPrompts.decompose` field of the `/plan` context envelope
|
|
24
|
+
* LLM in the `systemPrompts.decompose` field of the `/mandrel-plan` context envelope
|
|
25
25
|
* (via `lib/orchestration/planning/decomposer-context.js`), so no second
|
|
26
26
|
* verbatim copy can drift.
|
|
27
27
|
*/
|