mandrel 2.37.0 → 2.39.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 +61 -24
- package/.agents/agents/plan-critic.md +1 -1
- package/.agents/docs/SDLC.md +40 -40
- package/.agents/docs/agentrc-reference.json +1 -4
- package/.agents/docs/configuration.md +18 -18
- 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 +15 -16
- 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-skills-index.js +158 -75
- 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/changed-files.js +100 -9
- 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 +28 -10
- 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/qa/resolve-qa-contract.js +58 -6
- package/.agents/scripts/lib/signals/schema.js +1 -1
- package/.agents/scripts/lib/skills/skills-index.js +168 -0
- package/.agents/scripts/lib/skills/walk-skill-files.js +133 -9
- 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/quality-preview.js +50 -9
- 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/scripts/validate-skills.js +53 -66
- 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 +14 -6
- package/README.md +7 -7
- package/docs/CHANGELOG.md +23 -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
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
3
|
* plan-run-epilogue.js — execute the real per-run closeout for a
|
|
4
|
-
* multi-Story `/deliver`.
|
|
4
|
+
* multi-Story `/mandrel-deliver`.
|
|
5
5
|
*
|
|
6
6
|
* Usage:
|
|
7
7
|
* node .agents/scripts/plan-run-epilogue.js --stories 1,2,3
|
|
@@ -67,7 +67,7 @@ export async function main(argv = process.argv.slice(2), deps = {}) {
|
|
|
67
67
|
// along with the label itself. The epilogue is keyed on the delivered id
|
|
68
68
|
// set, and the synthesized `adhoc-<ids>` id it already used for positional
|
|
69
69
|
// runs is now the only id it needs.
|
|
70
|
-
// Range tokens expand here too (`--stories 101-104`): /deliver blesses the
|
|
70
|
+
// Range tokens expand here too (`--stories 101-104`): /mandrel-deliver blesses the
|
|
71
71
|
// dash range at the operator surface, so the id set the epilogue is keyed on
|
|
72
72
|
// must read the same shape. Rejecting a bad token is deliberate — the old
|
|
73
73
|
// silent filter turned a typo into an empty, wrongly-keyed rollup.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Story #3822 — single source of truth for the post-create board-add
|
|
5
5
|
* step. Issues created through any create path (`createTicket`,
|
|
6
|
-
* `createIssue` — which backs `/plan` persist and the `/plan`
|
|
6
|
+
* `createIssue` — which backs `/mandrel-plan` persist and the `/mandrel-plan`
|
|
7
7
|
* Phase 4 Epic open) must land on the configured Projects V2 board
|
|
8
8
|
* without relying on GitHub's "Auto-add to project" built-in workflow,
|
|
9
9
|
* which is off by default on fresh boards and cannot be enabled via API.
|
|
@@ -156,7 +156,7 @@ export function classifyGithubError(err) {
|
|
|
156
156
|
// Read-path callers (paginateRest, getTicket, getNativeSubIssues, …) all
|
|
157
157
|
// absorb the same jittered exponential backoff on transient GitHub errors
|
|
158
158
|
// through this one primitive, instead of bubbling a one-shot
|
|
159
|
-
// 502/429/ECONNRESET that kills a longer pipeline (e.g. the /deliver
|
|
159
|
+
// 502/429/ECONNRESET that kills a longer pipeline (e.g. the /mandrel-deliver
|
|
160
160
|
// Phase E retro). The network consumers repointed here
|
|
161
161
|
// (branch-protection, labels, projects-v2-graphql) call with no opts, so
|
|
162
162
|
// they adopt these defaults; their retry *classes* (the network blips) are
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* Epic-hierarchy write surface. It composed the exact `Epic: #N` footer that
|
|
16
16
|
* `pr-base-guard.js` hard-refuses at delivery, so the framework retained the
|
|
17
17
|
* ability to generate work it would then reject; it had no production caller
|
|
18
|
-
* (`/plan` persists through the bare `createIssue` below).
|
|
18
|
+
* (`/mandrel-plan` persists through the bare `createIssue` below).
|
|
19
19
|
*
|
|
20
20
|
* Public surface: `GitHubProvider.createIssue / getTicket /
|
|
21
21
|
* getTickets / updateTicket / getTicketDependencies / primeTicketCache /
|
|
@@ -251,8 +251,8 @@ export class TicketGateway {
|
|
|
251
251
|
|
|
252
252
|
/**
|
|
253
253
|
* Create a **bare** issue — no footer composition and no sub-issue link.
|
|
254
|
-
* Since Story #4545 this is the *only* create path: `/plan` persist and the
|
|
255
|
-
* `/plan` Phase 4 Epic open (`openEpicFromOnePager`'s `createIssue` port)
|
|
254
|
+
* Since Story #4545 this is the *only* create path: `/mandrel-plan` persist and the
|
|
255
|
+
* `/mandrel-plan` Phase 4 Epic open (`openEpicFromOnePager`'s `createIssue` port)
|
|
256
256
|
* both route through it.
|
|
257
257
|
*
|
|
258
258
|
* After the POST, the new issue is added to the configured Project V2
|
|
@@ -264,13 +264,13 @@ export class TicketGateway {
|
|
|
264
264
|
* The POST is wrapped in `withTransientRetry` (Story #4541) so it absorbs
|
|
265
265
|
* the same 502/429/ECONNRESET blips the read surfaces already do. It used
|
|
266
266
|
* to post bare, which made a single transient failure at story *k* of *N*
|
|
267
|
-
* abort `/plan` persist with `1..k-1` already live on the tracker.
|
|
267
|
+
* abort `/mandrel-plan` persist with `1..k-1` already live on the tracker.
|
|
268
268
|
*
|
|
269
269
|
* Retry alone is not sufficient for that failure mode — a POST whose
|
|
270
270
|
* response is lost would double-create on the retry. Story #5112 closed
|
|
271
271
|
* that: `findExisting` is consulted **before every retry POST**, and a hit
|
|
272
272
|
* is adopted instead of re-created, so a response-lost first attempt files
|
|
273
|
-
* exactly one issue. `/plan` persist supplies the plan-fingerprint lookup
|
|
273
|
+
* exactly one issue. `/mandrel-plan` persist supplies the plan-fingerprint lookup
|
|
274
274
|
* its resume path already uses (`plan-persist`'s `createStoryIssues`);
|
|
275
275
|
* callers with no content identity omit it and keep the pre-#5112
|
|
276
276
|
* retry-only behaviour.
|
|
@@ -405,7 +405,7 @@ export class TicketGateway {
|
|
|
405
405
|
*
|
|
406
406
|
* The additive POST goes through `withTransientRetry` (Story #4961) on the
|
|
407
407
|
* same policy as every other call in this file. Story #4952 raised the
|
|
408
|
-
* `/plan` write loops that reach this endpoint — the `agent::ready` flips
|
|
408
|
+
* `/mandrel-plan` write loops that reach this endpoint — the `agent::ready` flips
|
|
409
409
|
* and the checkpoint fan-out — off serial, which is precisely what makes
|
|
410
410
|
* GitHub's secondary rate limit likelier; `gh-exec` already classifies that
|
|
411
411
|
* as transient, so the only thing missing was a backoff behind it.
|
|
@@ -12,9 +12,18 @@
|
|
|
12
12
|
* 2. `npm run quality:watch` — chokidar wrapper re-emits on save.
|
|
13
13
|
* 3. `.husky/pre-commit` — block the commit on threshold violations.
|
|
14
14
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* pre-commit
|
|
15
|
+
* The pre-commit hook passes `--staged` and nothing else — the index is
|
|
16
|
+
* already the exact delta the operator is about to commit, and
|
|
17
|
+
* `tests/pre-commit-hook.test.js` pins that `--changed-since` stays off it.
|
|
18
|
+
* (This docblock previously claimed the hook passed `--changed-since HEAD`,
|
|
19
|
+
* describing a wiring the hook has not used for some time; the stale prose
|
|
20
|
+
* sent at least one bug report at the wrong flag — Story #5131.)
|
|
21
|
+
*
|
|
22
|
+
* `--staged` is merge-aware: while a merge is in progress the index is read
|
|
23
|
+
* against `MERGE_HEAD` rather than `HEAD`, so a base-sync merge commit is
|
|
24
|
+
* scored for the merging branch's own work and its conflict resolutions, not
|
|
25
|
+
* for everything the base branch landed. See `resolveMergeHead` in
|
|
26
|
+
* `lib/changed-files.js`.
|
|
18
27
|
*
|
|
19
28
|
* The CLI exits 0 when both envelopes report zero violations and the script
|
|
20
29
|
* could not surface a regression. Any violation in either envelope, or any
|
|
@@ -29,6 +38,7 @@ import {
|
|
|
29
38
|
runCrapPreview,
|
|
30
39
|
runMaintainabilityPreview,
|
|
31
40
|
} from './lib/baselines/preview-gates.js';
|
|
41
|
+
import { resolveMergeHead } from './lib/changed-files.js';
|
|
32
42
|
import { respondToHelp } from './lib/cli-usage.js';
|
|
33
43
|
import { getQuality, resolveConfig } from './lib/config-resolver.js';
|
|
34
44
|
import { resolveCyclomaticPolicy } from './lib/cyclomatic-ceiling.js';
|
|
@@ -39,7 +49,10 @@ const USAGE = {
|
|
|
39
49
|
summary:
|
|
40
50
|
'Preview the per-file maintainability and CRAP deltas for the change set, and exit non-zero on any threshold violation.',
|
|
41
51
|
flags: [
|
|
42
|
-
[
|
|
52
|
+
[
|
|
53
|
+
'--staged',
|
|
54
|
+
'Score the git index only (the pre-commit-hook scope). During a merge the index is read against MERGE_HEAD.',
|
|
55
|
+
],
|
|
43
56
|
[
|
|
44
57
|
'--changed-since <ref>',
|
|
45
58
|
'Score the diff against <ref> (default: HEAD). Last occurrence wins.',
|
|
@@ -388,6 +401,35 @@ function runGateSafely(runner, args, label, stderr) {
|
|
|
388
401
|
});
|
|
389
402
|
}
|
|
390
403
|
|
|
404
|
+
/**
|
|
405
|
+
* Render the scope header line.
|
|
406
|
+
*
|
|
407
|
+
* Story #5131 — when `--staged` runs during a merge the scope is re-based to
|
|
408
|
+
* `MERGE_HEAD`, and the header says so. Without that line the operator sees a
|
|
409
|
+
* table whose row count does not match `git diff --cached` with no way to tell
|
|
410
|
+
* the narrowing was deliberate.
|
|
411
|
+
*
|
|
412
|
+
* The merge state is resolved here rather than read back off a gate envelope's
|
|
413
|
+
* `summary.diffRef`: that field means "the ref this scope was resolved
|
|
414
|
+
* against" for every scope kind, so anything that populates it — a future
|
|
415
|
+
* scope mode, a test stub — would render a merge banner over a repo that is
|
|
416
|
+
* not merging. Resolving it after the `!staged` early return also keeps the
|
|
417
|
+
* probe off the `--changed-since` path, which has no use for it.
|
|
418
|
+
*
|
|
419
|
+
* @param {{ staged: boolean, ref: string|null, cwd: string }} args
|
|
420
|
+
* @returns {string}
|
|
421
|
+
*/
|
|
422
|
+
function stagedScopeLine({ staged, ref, cwd }) {
|
|
423
|
+
if (!staged) return `scope=diff ref=${ref}\n\n`;
|
|
424
|
+
const mergeHead = resolveMergeHead({ cwd });
|
|
425
|
+
if (!mergeHead) return 'scope=staged (git diff --cached)\n\n';
|
|
426
|
+
return (
|
|
427
|
+
`scope=staged (git diff --cached ${mergeHead.slice(0, 12)}) — merge in ` +
|
|
428
|
+
"progress: scored against MERGE_HEAD, not HEAD, so the base branch's " +
|
|
429
|
+
'incoming files are excluded\n\n'
|
|
430
|
+
);
|
|
431
|
+
}
|
|
432
|
+
|
|
391
433
|
/**
|
|
392
434
|
* Write the run's report — the `--json` envelope, or the human-readable
|
|
393
435
|
* table plus any gate diagnostics and the non-zero-exit summary.
|
|
@@ -401,6 +443,7 @@ function runGateSafely(runner, args, label, stderr) {
|
|
|
401
443
|
* json: boolean,
|
|
402
444
|
* staged: boolean,
|
|
403
445
|
* ref: string|null,
|
|
446
|
+
* cwd: string,
|
|
404
447
|
* miResult: {exitCode: number, envelope: object|null},
|
|
405
448
|
* crapResult: {exitCode: number, envelope: object|null},
|
|
406
449
|
* merged: ReturnType<typeof mergeEnvelopes>,
|
|
@@ -413,6 +456,7 @@ function emitReport({
|
|
|
413
456
|
json,
|
|
414
457
|
staged,
|
|
415
458
|
ref,
|
|
459
|
+
cwd,
|
|
416
460
|
miResult,
|
|
417
461
|
crapResult,
|
|
418
462
|
merged,
|
|
@@ -438,11 +482,7 @@ function emitReport({
|
|
|
438
482
|
return;
|
|
439
483
|
}
|
|
440
484
|
stdout.write('\n--- quality:preview ---\n');
|
|
441
|
-
stdout.write(
|
|
442
|
-
staged
|
|
443
|
-
? 'scope=staged (git diff --cached)\n\n'
|
|
444
|
-
: `scope=diff ref=${ref}\n\n`,
|
|
445
|
-
);
|
|
485
|
+
stdout.write(stagedScopeLine({ staged, ref, cwd }));
|
|
446
486
|
stdout.write(`${renderTable(merged)}\n`);
|
|
447
487
|
const diagnostics = renderDiagnostics([miResult, crapResult]);
|
|
448
488
|
if (diagnostics) stdout.write(`\n${diagnostics}\n`);
|
|
@@ -518,6 +558,7 @@ export async function runCli({
|
|
|
518
558
|
json,
|
|
519
559
|
staged,
|
|
520
560
|
ref,
|
|
561
|
+
cwd,
|
|
521
562
|
miResult,
|
|
522
563
|
crapResult,
|
|
523
564
|
merged,
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* resolve-stories.js — resolve a list of Story ids into the
|
|
5
|
-
* `{ stories, dag, done }` envelope `/deliver` sequences from.
|
|
5
|
+
* `{ stories, dag, done }` envelope `/mandrel-deliver` sequences from.
|
|
6
6
|
*
|
|
7
|
-
* This is the ONE resolution step for multi-Story delivery. `/deliver` takes
|
|
7
|
+
* This is the ONE resolution step for multi-Story delivery. `/mandrel-deliver` takes
|
|
8
8
|
* only Story ids; the graph is discovered here, from live state, rather than
|
|
9
9
|
* hand-transcribed by the host or implied by a batch label.
|
|
10
10
|
*
|
|
@@ -63,7 +63,7 @@ const HELP = `\
|
|
|
63
63
|
Usage:
|
|
64
64
|
resolve-stories.js --ids <n,n,...> [--pretty] [--no-native]
|
|
65
65
|
|
|
66
|
-
Resolve Story ids into the { stories, dag, done } envelope /deliver sequences
|
|
66
|
+
Resolve Story ids into the { stories, dag, done } envelope /mandrel-deliver sequences
|
|
67
67
|
from. Dependencies are discovered from live state: body edges union native
|
|
68
68
|
blocked_by edges, with every blocker (in-set or foreign) resolved against its
|
|
69
69
|
real issue state.
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* resync-status-column.js — re-assert the GitHub Projects v2 Status
|
|
6
6
|
* column for a ticket after auto-merge has fired (Story #2845).
|
|
7
7
|
*
|
|
8
|
-
* The `/single-story-deliver` and `/deliver` workflow docs call
|
|
8
|
+
* The `/single-story-deliver` and `/mandrel-deliver` workflow docs call
|
|
9
9
|
* this CLI after Step 5 confirms `state: "MERGED"` so the orchestrator
|
|
10
10
|
* wins the race against the GitHub built-in `Pull request merged`
|
|
11
11
|
* workflow, which would otherwise overwrite Status to whatever value
|
|
@@ -84,7 +84,7 @@ const tasks = [
|
|
|
84
84
|
nodeGate('lifecycle-lint', '.agents/scripts/check-lifecycle-lint.js'),
|
|
85
85
|
// Workflow prose surface (Epic #4474 PR5). No workflow may instruct calling
|
|
86
86
|
// an exported library function that has no CLI entrypoint — the measured
|
|
87
|
-
// shim-writing failure mode the /plan collapse killed. See
|
|
87
|
+
// shim-writing failure mode the /mandrel-plan collapse killed. See
|
|
88
88
|
// check-workflow-cli-lint.js for the paragraph-level heuristic.
|
|
89
89
|
nodeGate('workflow-cli-lint', '.agents/scripts/check-workflow-cli-lint.js'),
|
|
90
90
|
// Label-vocabulary citations in `.agents/docs/SDLC.md` and
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* single-story-close.js — Close a Story against `main` (v2 `/deliver` path).
|
|
4
|
+
* single-story-close.js — Close a Story against `main` (v2 `/mandrel-deliver` path).
|
|
5
5
|
*
|
|
6
|
-
* Thin CLI entry for `/deliver` / `helpers/deliver-story`. Opens a PR from
|
|
6
|
+
* Thin CLI entry for `/mandrel-deliver` / `helpers/deliver-story`. Opens a PR from
|
|
7
7
|
* `story-<id>` to `project.baseBranch`, runs Story-scope review, and arms
|
|
8
8
|
* auto-merge. There is no Epic parent, epic-merge-lock, or wave merge.
|
|
9
9
|
*
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/* node:coverage ignore file */
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* single-story-init.js — Initialize a Story for v2 `/deliver`.
|
|
5
|
+
* single-story-init.js — Initialize a Story for v2 `/mandrel-deliver`.
|
|
6
6
|
*
|
|
7
7
|
* Seeds `story-<id>` from `project.baseBranch` (default `main`), materialises
|
|
8
8
|
* the per-Story worktree when isolation is enabled, upserts a `story-init`
|
|
@@ -122,7 +122,7 @@ export function assertDeliverableStory(story, storyId) {
|
|
|
122
122
|
if (!story.labels.includes(TYPE_LABELS.STORY)) {
|
|
123
123
|
throw new Error(
|
|
124
124
|
`Issue #${storyId} is not a Story (labels: ${story.labels.join(', ')}). ` +
|
|
125
|
-
'v2 /deliver accepts type::story tickets only.',
|
|
125
|
+
'v2 /mandrel-deliver accepts type::story tickets only.',
|
|
126
126
|
);
|
|
127
127
|
}
|
|
128
128
|
if (story.state === 'closed') {
|
|
@@ -132,7 +132,7 @@ export function assertDeliverableStory(story, storyId) {
|
|
|
132
132
|
if (/\b(?:Epic|Parent):\s*#\d+/i.test(body)) {
|
|
133
133
|
throw new Error(
|
|
134
134
|
`Story #${storyId} still declares an Epic/Parent footer. ` +
|
|
135
|
-
'v2 delivery is Story-only — re-plan as a standalone Story before /deliver.',
|
|
135
|
+
'v2 delivery is Story-only — re-plan as a standalone Story before /mandrel-deliver.',
|
|
136
136
|
);
|
|
137
137
|
}
|
|
138
138
|
}
|
|
@@ -189,7 +189,7 @@ export async function assertNotForeignExecuting({
|
|
|
189
189
|
(lease.previousOwner
|
|
190
190
|
? ` (assignee @${lease.previousOwner})`
|
|
191
191
|
: ' with no assignee') +
|
|
192
|
-
'. Another /deliver run may already own it. Confirm that run is dead, ' +
|
|
192
|
+
'. Another /mandrel-deliver run may already own it. Confirm that run is dead, ' +
|
|
193
193
|
'then re-run with --steal to take it.',
|
|
194
194
|
);
|
|
195
195
|
}
|
|
@@ -607,7 +607,7 @@ export async function runSingleStoryInit({
|
|
|
607
607
|
);
|
|
608
608
|
progress('INIT', `Initializing standalone Story #${storyId}...`);
|
|
609
609
|
|
|
610
|
-
// Issue #4483 — deterministic remote evidence at the v2 `/deliver` entry
|
|
610
|
+
// Issue #4483 — deterministic remote evidence at the v2 `/mandrel-deliver` entry
|
|
611
611
|
// seam (`single-story-init.js`). The
|
|
612
612
|
// probe is read-only, so it runs under --dry-run too. The CLI records
|
|
613
613
|
// the fact; the workflow owns the `agent::blocked` transition on
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* stories-wave-tick.js — continuous ready-set planner for the standalone
|
|
5
|
-
* `/deliver` story-list path.
|
|
5
|
+
* `/mandrel-deliver` story-list path.
|
|
6
6
|
*
|
|
7
7
|
* Thin **adapter** over the path-agnostic ready-set scheduling core
|
|
8
8
|
* (`lib/wave-runner/ready-set.js#planReadySet`). It emits the set of
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* **Two modes, one kernel.**
|
|
22
22
|
*
|
|
23
23
|
* - **Probe mode** (`--stories <csv> --probe-live [--dispatched <csv>]`) is
|
|
24
|
-
* the canonical `/deliver` beat: the graph, the done set, and the in-flight
|
|
24
|
+
* the canonical `/mandrel-deliver` beat: the graph, the done set, and the in-flight
|
|
25
25
|
* count are resolved from **live state** via `lib/wave-runner/live-probe.js`.
|
|
26
26
|
* The caller supplies ids, so there is no accounting to hand-maintain
|
|
27
27
|
* across beats — the seed-the-first-beat's-`--done` footgun the workflow
|
|
@@ -97,14 +97,14 @@
|
|
|
97
97
|
* `--done` and `ready` is empty.
|
|
98
98
|
*
|
|
99
99
|
* The per-beat concurrency cap is resolved from the same config seam
|
|
100
|
-
* `/deliver` uses — `resolveConfig` + `getRunners` reading
|
|
100
|
+
* `/mandrel-deliver` uses — `resolveConfig` + `getRunners` reading
|
|
101
101
|
* `delivery.deliverRunner.concurrencyCap` (default 3) — so a
|
|
102
102
|
* `.agentrc.local.json` override is honored. A `--concurrency <n>` CLI flag
|
|
103
103
|
* overrides the config-resolved value for that run only, and the envelope's
|
|
104
104
|
* `capPrecedence` names which source won so the override is never silent
|
|
105
105
|
* (Story #4875). This shares one
|
|
106
106
|
* deterministic config source (`delivery.deliverRunner.concurrencyCap`) and
|
|
107
|
-
* one scheduling kernel with every `/deliver` multi-Story invocation.
|
|
107
|
+
* one scheduling kernel with every `/mandrel-deliver` multi-Story invocation.
|
|
108
108
|
*
|
|
109
109
|
* Exit codes: 0 ok · 1 input error · 2 dependency cycle (`cycleError`) ·
|
|
110
110
|
* 3 wedged (`wedged`) — ready is empty, nothing is in flight, and undone
|
|
@@ -170,7 +170,7 @@ and the same file-overlap guard as planReadySet.
|
|
|
170
170
|
|
|
171
171
|
Two modes:
|
|
172
172
|
--probe-live Resolve the graph and derive done / in-flight from LIVE state
|
|
173
|
-
(the canonical /deliver beat). Nothing is hand-maintained
|
|
173
|
+
(the canonical /mandrel-deliver beat). Nothing is hand-maintained
|
|
174
174
|
across beats. Mutually exclusive with --dag/--dag-file/--done/
|
|
175
175
|
--in-flight. Adds "done" and "epilogueDue" to the envelope.
|
|
176
176
|
--dag Legacy flag mode: the caller supplies the graph and the run
|
|
@@ -662,7 +662,7 @@ export function parseConcurrencyOverride(raw) {
|
|
|
662
662
|
/**
|
|
663
663
|
* Resolve the per-beat concurrency cap.
|
|
664
664
|
*
|
|
665
|
-
* Mirrors the `/deliver` multi-Story seam (`helpers/deliver-story.md`): resolve the
|
|
665
|
+
* Mirrors the `/mandrel-deliver` multi-Story seam (`helpers/deliver-story.md`): resolve the
|
|
666
666
|
* project config (which deep-merges `.agentrc.local.json` over `.agentrc.json`)
|
|
667
667
|
* then read `delivery.deliverRunner.concurrencyCap` via `getRunners` (default
|
|
668
668
|
* 3). An explicit `override` (the `--concurrency <n>` CLI flag) wins over
|
|
@@ -855,7 +855,7 @@ export function buildReadySetEnvelope(
|
|
|
855
855
|
return {
|
|
856
856
|
envelope: {
|
|
857
857
|
...base,
|
|
858
|
-
cycleError: `Dependency cycle detected: ${cycle.join(' → ')}. Fix the depends_on declarations before running /deliver.`,
|
|
858
|
+
cycleError: `Dependency cycle detected: ${cycle.join(' → ')}. Fix the depends_on declarations before running /mandrel-deliver.`,
|
|
859
859
|
},
|
|
860
860
|
exitCode: 2,
|
|
861
861
|
};
|
|
@@ -1087,7 +1087,7 @@ export function runStoriesWaveTick({
|
|
|
1087
1087
|
*
|
|
1088
1088
|
* This is the flag-free beat. The caller supplies only the Story ids it was
|
|
1089
1089
|
* asked to deliver; `done` and `inFlight` are probed rather than transcribed,
|
|
1090
|
-
* which is what makes the `/deliver` loop's old seed-the-first-beat footgun
|
|
1090
|
+
* which is what makes the `/mandrel-deliver` loop's old seed-the-first-beat footgun
|
|
1091
1091
|
* structurally impossible instead of merely documented.
|
|
1092
1092
|
*
|
|
1093
1093
|
* The envelope is the flag mode's, plus three probe-only fields the caller can
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// .agents/scripts/validate-skills.js
|
|
3
3
|
//
|
|
4
|
-
// Walk
|
|
4
|
+
// Walk `SKILL.md` under both skills roots — the package payload
|
|
5
|
+
// (`.agents/skills/{core,stack}/`) and the consumer-writable local zone
|
|
6
|
+
// (`.agents/local/skills/{core,stack}/`, Story #5135) — via the shared parser
|
|
5
7
|
// helper, validate each frontmatter block against
|
|
6
8
|
// `.agents/schemas/skill.schema.json`, enforce Policy Capsule presence
|
|
7
|
-
// (5–12 bullets), and verify membership in
|
|
8
|
-
//
|
|
9
|
+
// (5–12 bullets), and verify membership in each root's own manifest when it
|
|
10
|
+
// exists. A consumer-authored skill is held to exactly the same bar as a
|
|
11
|
+
// shipped one; the roots are validated separately because each carries its
|
|
12
|
+
// own index (the shipped manifest is a payload file and must stay
|
|
13
|
+
// payload-only — see generate-skills-index.js). All findings are batched into a single
|
|
9
14
|
// human-readable report; the process exits non-zero when any finding is
|
|
10
15
|
// surfaced.
|
|
11
16
|
//
|
|
@@ -30,7 +35,17 @@ import { parseStandardCliArgs } from './lib/cli/standard-args.js';
|
|
|
30
35
|
import { runAsCli } from './lib/cli-utils.js';
|
|
31
36
|
import { Logger } from './lib/Logger.js';
|
|
32
37
|
import { parseSkill } from './lib/skills/parse-skill.js';
|
|
33
|
-
import {
|
|
38
|
+
import {
|
|
39
|
+
auditIndex,
|
|
40
|
+
indexPathFor,
|
|
41
|
+
readIndexPaths,
|
|
42
|
+
} from './lib/skills/skills-index.js';
|
|
43
|
+
import {
|
|
44
|
+
collectLocalSkillFiles,
|
|
45
|
+
collectSkillFiles,
|
|
46
|
+
LOCAL_SKILLS_SEGMENTS,
|
|
47
|
+
PAYLOAD_SKILLS_SEGMENTS,
|
|
48
|
+
} from './lib/skills/walk-skill-files.js';
|
|
34
49
|
|
|
35
50
|
const MIN_CAPSULE_BULLETS = 5;
|
|
36
51
|
const MAX_CAPSULE_BULLETS = 12;
|
|
@@ -118,56 +133,11 @@ function buildManifestValidator(repoRoot) {
|
|
|
118
133
|
}
|
|
119
134
|
|
|
120
135
|
/**
|
|
121
|
-
* Read
|
|
122
|
-
*
|
|
123
|
-
* is present and parseable, or null otherwise.
|
|
136
|
+
* Read one root's manifest into the `{ exists, paths, manifest, indexPath }`
|
|
137
|
+
* shape the findings pass consumes.
|
|
124
138
|
*/
|
|
125
|
-
function readIndex(repoRoot) {
|
|
126
|
-
|
|
127
|
-
repoRoot,
|
|
128
|
-
'.agents',
|
|
129
|
-
'skills',
|
|
130
|
-
'skills.index.json',
|
|
131
|
-
);
|
|
132
|
-
if (!fs.existsSync(indexPath)) {
|
|
133
|
-
return { exists: false, paths: null, manifest: null, indexPath };
|
|
134
|
-
}
|
|
135
|
-
try {
|
|
136
|
-
const manifest = JSON.parse(fs.readFileSync(indexPath, 'utf8'));
|
|
137
|
-
const paths = new Set(
|
|
138
|
-
Array.isArray(manifest.skills)
|
|
139
|
-
? manifest.skills
|
|
140
|
-
.map((s) => s.path)
|
|
141
|
-
.filter((p) => typeof p === 'string')
|
|
142
|
-
: [],
|
|
143
|
-
);
|
|
144
|
-
return { exists: true, paths, manifest, indexPath };
|
|
145
|
-
} catch (err) {
|
|
146
|
-
return {
|
|
147
|
-
exists: true,
|
|
148
|
-
paths: null,
|
|
149
|
-
manifest: null,
|
|
150
|
-
indexPath,
|
|
151
|
-
parseError: err.message,
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* Validate a parsed manifest against skills-index.schema.json. Returns
|
|
158
|
-
* finding strings tagged with the `manifest-schema` pillar.
|
|
159
|
-
*/
|
|
160
|
-
function validateManifestSchema(manifest, indexRelPath, validateManifest) {
|
|
161
|
-
const findings = [];
|
|
162
|
-
if (!validateManifest(manifest)) {
|
|
163
|
-
for (const err of validateManifest.errors ?? []) {
|
|
164
|
-
const where = err.instancePath || '(root)';
|
|
165
|
-
findings.push(
|
|
166
|
-
`${indexRelPath}: manifest-schema: schema violation at ${where}: ${err.message}`,
|
|
167
|
-
);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
return findings;
|
|
139
|
+
function readIndex(repoRoot, rootSegments = PAYLOAD_SKILLS_SEGMENTS) {
|
|
140
|
+
return readIndexPaths(indexPathFor(repoRoot, rootSegments));
|
|
171
141
|
}
|
|
172
142
|
|
|
173
143
|
/**
|
|
@@ -216,6 +186,7 @@ function rel(absPath, repoRoot) {
|
|
|
216
186
|
/**
|
|
217
187
|
* Pure entry point used by tests. Returns `{ status, output, findings }`.
|
|
218
188
|
*/
|
|
189
|
+
|
|
219
190
|
export function run({ argv = [], repoRoot } = {}) {
|
|
220
191
|
const parsed = parseArgs(argv);
|
|
221
192
|
if (parsed.help) {
|
|
@@ -234,25 +205,41 @@ export function run({ argv = [], repoRoot } = {}) {
|
|
|
234
205
|
const indexRel = rel(indexInfo.indexPath, root);
|
|
235
206
|
|
|
236
207
|
const findings = [];
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
);
|
|
241
|
-
} else if (indexInfo.paths === null) {
|
|
242
|
-
findings.push(`index unparseable: ${indexRel} — ${indexInfo.parseError}`);
|
|
243
|
-
} else if (indexInfo.manifest !== null) {
|
|
244
|
-
findings.push(
|
|
245
|
-
...validateManifestSchema(indexInfo.manifest, indexRel, validateManifest),
|
|
246
|
-
);
|
|
247
|
-
}
|
|
208
|
+
findings.push(
|
|
209
|
+
...auditIndex(indexInfo, indexRel, validateManifest, { required: true }),
|
|
210
|
+
);
|
|
248
211
|
|
|
249
|
-
const
|
|
212
|
+
const payloadFiles = collectSkillFiles(root);
|
|
250
213
|
const indexPaths =
|
|
251
214
|
indexInfo.exists && indexInfo.paths !== null ? indexInfo.paths : null;
|
|
252
|
-
for (const file of
|
|
215
|
+
for (const file of payloadFiles) {
|
|
253
216
|
findings.push(...validateOne(file, root, validateFrontmatter, indexPaths));
|
|
254
217
|
}
|
|
255
218
|
|
|
219
|
+
// The local zone is optional: a repo with no consumer-authored skills has
|
|
220
|
+
// no local root and no local index, and that is a clean run, not a finding.
|
|
221
|
+
const localFiles = collectLocalSkillFiles(root);
|
|
222
|
+
if (localFiles.length > 0) {
|
|
223
|
+
const localIndexInfo = readIndex(root, LOCAL_SKILLS_SEGMENTS);
|
|
224
|
+
const localIndexRel = rel(localIndexInfo.indexPath, root);
|
|
225
|
+
findings.push(
|
|
226
|
+
...auditIndex(localIndexInfo, localIndexRel, validateManifest, {
|
|
227
|
+
required: true,
|
|
228
|
+
}),
|
|
229
|
+
);
|
|
230
|
+
const localIndexPaths =
|
|
231
|
+
localIndexInfo.exists && localIndexInfo.paths !== null
|
|
232
|
+
? localIndexInfo.paths
|
|
233
|
+
: null;
|
|
234
|
+
for (const file of localFiles) {
|
|
235
|
+
findings.push(
|
|
236
|
+
...validateOne(file, root, validateFrontmatter, localIndexPaths),
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const skillFiles = [...payloadFiles, ...localFiles];
|
|
242
|
+
|
|
256
243
|
if (findings.length === 0) {
|
|
257
244
|
Logger.info(`validate-skills: ${skillFiles.length} skill(s) passed`);
|
|
258
245
|
return { status: 0, output: '', findings };
|
|
@@ -13,7 +13,7 @@ description:
|
|
|
13
13
|
- Phase 1 MUST restate the idea as a "How Might We" statement, ask 3–5 sharpening questions via `AskUserQuestion`, and generate 5–8 variations (never 20+ shallow ones) — each carrying a reason it exists, told as a short story, not a bare bullet. Do not proceed until target user and success criteria are explicit.
|
|
14
14
|
- Phase 2 grill loop poses **one** question at a time, each with a recommended answer + one-line rationale grounded in user input / codebase / first principles; never batch questions and never omit the recommendation.
|
|
15
15
|
- Re-enumerate open branches after every grill answer; stop only when no unresolved decisions remain. Take the off-ramp directly to Phase 3 when the idea is already crisply scoped. A branch consciously deferred rather than resolved records its deferral reason.
|
|
16
|
-
- Phase 3 emits a markdown one-pager with the canonical five planning headings exactly: `## Context`, `## Goal`, `## Non-Goals`, `## Scope`, `## Acceptance Criteria` (plus optional `## Open Questions`). No alternate heading text — the `/plan` clarity gate depends on this verbatim.
|
|
16
|
+
- Phase 3 emits a markdown one-pager with the canonical five planning headings exactly: `## Context`, `## Goal`, `## Non-Goals`, `## Scope`, `## Acceptance Criteria` (plus optional `## Open Questions`). No alternate heading text — the `/mandrel-plan` clarity gate depends on this verbatim.
|
|
17
17
|
- Surface every key assumption inside `## Context` (or `## Scope`); assumptions do not get their own heading. Unresolved decisions MUST NOT carry into the one-pager.
|
|
18
18
|
- The `## Non-Goals` list is mandatory and each entry includes a reason — focus is created by explicit exclusion.
|
|
19
19
|
- Be honest, not supportive: push back on weak ideas with kindness; never function as a yes-machine.
|
|
@@ -22,10 +22,10 @@ description:
|
|
|
22
22
|
|
|
23
23
|
## Activation
|
|
24
24
|
|
|
25
|
-
Called from [`/plan`](../../../workflows/plan.md) during ideation when the
|
|
25
|
+
Called from [`/mandrel-plan`](../../../workflows/mandrel-plan.md) during ideation when the
|
|
26
26
|
operator supplies `--seed "<text>"` (or runs ideation with no seed and the host
|
|
27
27
|
collects one interactively). The skill sharpens freeform intent into the
|
|
28
|
-
canonical planning sections that `/plan` then folds into a Story. There is no
|
|
28
|
+
canonical planning sections that `/mandrel-plan` then folds into a Story. There is no
|
|
29
29
|
separate Epic Clarity Gate path in v2 — N=1 Story authoring with a folded
|
|
30
30
|
`## Spec` is the lean default.
|
|
31
31
|
|
|
@@ -134,9 +134,9 @@ clothes — inside the grill loop, not after the one-pager is written.
|
|
|
134
134
|
#### Phase 3: Sharpen & Ship
|
|
135
135
|
|
|
136
136
|
Produce a markdown one-pager that moves work forward. The five canonical
|
|
137
|
-
headings below match `.agents/templates/epic-from-idea.md` and the `/plan`
|
|
137
|
+
headings below match `.agents/templates/epic-from-idea.md` and the `/mandrel-plan`
|
|
138
138
|
clarity gate; emit them verbatim so the renderer can substitute the body into a
|
|
139
|
-
`/plan` Story seed without translation.
|
|
139
|
+
`/mandrel-plan` Story seed without translation.
|
|
140
140
|
|
|
141
141
|
```markdown
|
|
142
142
|
# [Idea Name]
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: scope-triage
|
|
3
3
|
description:
|
|
4
|
-
Optional split-advisory for `/plan`. Under v2 there is no epic|story routing
|
|
5
|
-
verdict — `/plan` always authors Stories. Use this skill only when judging
|
|
4
|
+
Optional split-advisory for `/mandrel-plan`. Under v2 there is no epic|story routing
|
|
5
|
+
verdict — `/mandrel-plan` always authors Stories. Use this skill only when judging
|
|
6
6
|
whether a draft should stay one Story or legitimately split (near-zero
|
|
7
7
|
overlap or an architectural seam).
|
|
8
8
|
---
|
|
@@ -11,7 +11,7 @@ description:
|
|
|
11
11
|
|
|
12
12
|
## Policy Capsule
|
|
13
13
|
|
|
14
|
-
- There is **no** `epic | story | borderline` routing verdict in v2. `/plan`
|
|
14
|
+
- There is **no** `epic | story | borderline` routing verdict in v2. `/mandrel-plan`
|
|
15
15
|
is a single path that emits **one Story by default**.
|
|
16
16
|
- This skill is an optional **split advisory**: should the author keep one
|
|
17
17
|
Story, or does the seed clear the default-single split policy?
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
"tier": "core",
|
|
98
98
|
"category": "core",
|
|
99
99
|
"path": ".agents/skills/core/scope-triage/SKILL.md",
|
|
100
|
-
"description": "Optional split-advisory for `/plan`. Under v2 there is no epic|story routing verdict — `/plan` always authors Stories. Use this skill only when judging whether a draft should stay one Story or legitimately split (near-zero overlap or an architectural seam).",
|
|
100
|
+
"description": "Optional split-advisory for `/mandrel-plan`. Under v2 there is no epic|story routing verdict — `/mandrel-plan` always authors Stories. Use this skill only when judging whether a draft should stay one Story or legitimately split (near-zero overlap or an architectural seam).",
|
|
101
101
|
"policyCapsuleBullets": 5,
|
|
102
102
|
"allowedTools": null,
|
|
103
103
|
"vendor": null
|
|
@@ -170,7 +170,7 @@ Record each `F#` finding as a `QaLedgerItem` on the shared session ledger under
|
|
|
170
170
|
`temp/qa/`, then route the ledger through the shared classify → route →
|
|
171
171
|
disposition → promote core — both stated once in
|
|
172
172
|
[`qa-core.md`](../../../../workflows/helpers/qa-core.md). The harness **MUST
|
|
173
|
-
NOT** create tickets autonomously: findings are promoted through `/plan` only
|
|
173
|
+
NOT** create tickets autonomously: findings are promoted through `/mandrel-plan` only
|
|
174
174
|
after the operator confirms each disposition at the HITL write gate. That gate
|
|
175
175
|
is the safety boundary against spurious filing.
|
|
176
176
|
|
|
@@ -27,7 +27,7 @@ than empty findings. The applicability probe (`hasPersistenceLayer` in
|
|
|
27
27
|
[`lib/audit-suite/selector.js`](../scripts/lib/audit-suite/selector.js), gated
|
|
28
28
|
by `target: "data-model"` in
|
|
29
29
|
[`schemas/audit-rules.json`](../schemas/audit-rules.json)) makes this decision
|
|
30
|
-
automatically in `/deliver` and plan-run modes; in a manual invocation you MUST
|
|
30
|
+
automatically in `/mandrel-deliver` and plan-run modes; in a manual invocation you MUST
|
|
31
31
|
make the same determination yourself before reading anything else.
|
|
32
32
|
|
|
33
33
|
## Scope
|
|
@@ -188,7 +188,7 @@ auditable.
|
|
|
188
188
|
## Periodic full-scope sweep
|
|
189
189
|
|
|
190
190
|
Context Economy findings accrete slowly — a doc that is lean today grows a
|
|
191
|
-
bloated tail over many deliveries, and no single change-set-scoped `/deliver`
|
|
191
|
+
bloated tail over many deliveries, and no single change-set-scoped `/mandrel-deliver`
|
|
192
192
|
run sees the whole picture. Run this lens **full-scope** on a
|
|
193
193
|
recurring cadence so the drift is caught before it compounds:
|
|
194
194
|
|
|
@@ -202,7 +202,7 @@ recurring cadence so the drift is caught before it compounds:
|
|
|
202
202
|
Route the resulting `audit-documentation-results.md` through
|
|
203
203
|
[`/audit-to-stories`](audit-to-stories.md), which groups the findings,
|
|
204
204
|
deduplicates them against existing Issues by fingerprint, and opens
|
|
205
|
-
remediation Stories (or chains into `/plan --seed`) so the Context-Economy
|
|
205
|
+
remediation Stories (or chains into `/mandrel-plan --seed`) so the Context-Economy
|
|
206
206
|
findings land as actionable, tracked work rather than a report nobody reads.
|
|
207
207
|
|
|
208
208
|
## Constraint (lens-specific carve-out)
|