mandrel 1.59.0 → 1.61.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 +86 -44
- package/.agents/docs/SDLC.md +135 -141
- package/.agents/docs/configuration.md +77 -20
- package/.agents/docs/quality-gates.md +796 -0
- package/.agents/docs/workflows.md +6 -9
- package/.agents/instructions.md +12 -11
- package/.agents/personas/architect.md +1 -1
- package/.agents/personas/product.md +1 -1
- package/.agents/personas/project-manager.md +14 -14
- package/.agents/personas/technical-writer.md +1 -1
- package/.agents/rules/changelog-style.md +5 -5
- package/.agents/rules/git-conventions.md +3 -3
- package/.agents/runtime-deps.json +2 -2
- package/.agents/schemas/agentrc.schema.json +3 -3
- package/.agents/schemas/dispatch-manifest.json +4 -4
- package/.agents/schemas/epic-spec.schema.json +15 -45
- package/.agents/schemas/lifecycle/README.md +1 -1
- package/.agents/schemas/lifecycle/story.dispatch.end.schema.json +1 -1
- package/.agents/schemas/lifecycle/story.dispatch.start.schema.json +1 -1
- package/.agents/schemas/lifecycle/story.heartbeat.schema.json +1 -1
- package/.agents/schemas/validation-evidence.schema.json +1 -1
- package/.agents/scripts/README.md +2 -2
- package/.agents/scripts/acceptance-eval.js +1 -1
- package/.agents/scripts/acceptance-spec-reconciler.js +2 -2
- package/.agents/scripts/agents-bootstrap-github.js +23 -119
- package/.agents/scripts/analyze-execution.js +2 -2
- package/.agents/scripts/audit-to-stories.js +1 -1
- package/.agents/scripts/check-doc-links.js +2 -3
- package/.agents/scripts/diagnose-friction.js +1 -1
- package/.agents/scripts/dispatcher.js +2 -2
- package/.agents/scripts/drain-pending-cleanup.js +1 -1
- package/.agents/scripts/epic-audit-prepare.js +3 -3
- package/.agents/scripts/epic-deliver-note-intervention.js +2 -2
- package/.agents/scripts/epic-deliver-preflight.js +6 -6
- package/.agents/scripts/epic-deliver-prepare.js +1 -1
- package/.agents/scripts/epic-execute-record-wave.js +4 -4
- package/.agents/scripts/epic-plan-healthcheck.js +6 -10
- package/.agents/scripts/epic-plan-spec-validate.js +1 -1
- package/.agents/scripts/epic-reconcile.js +11 -29
- package/.agents/scripts/evidence-gate.js +1 -1
- package/.agents/scripts/generate-workflows-doc.js +1 -1
- package/.agents/scripts/hierarchy-gate.js +7 -11
- package/.agents/scripts/lib/ITicketingProvider.js +1 -1
- package/.agents/scripts/lib/audit-suite/selector.js +1 -1
- package/.agents/scripts/lib/audit-to-stories/seed-epic-from-findings.js +2 -2
- package/.agents/scripts/lib/baseline-snapshot.js +7 -7
- package/.agents/scripts/lib/bdd-runner-detect.js +1 -1
- package/.agents/scripts/lib/bdd-scenario-scanner.js +3 -3
- package/.agents/scripts/lib/bootstrap/baselines-layout-migration.js +1 -1
- package/.agents/scripts/lib/bootstrap/branch-protection.js +1 -1
- package/.agents/scripts/lib/bootstrap/ci-workflow-template.js +47 -1
- package/.agents/scripts/lib/bootstrap/commit-push.js +2 -2
- package/.agents/scripts/lib/bootstrap/gh-preflight.js +7 -9
- package/.agents/scripts/lib/bootstrap/manifest.js +21 -1
- package/.agents/scripts/lib/bootstrap/merge-methods.js +31 -16
- package/.agents/scripts/lib/bootstrap/project-bootstrap.js +32 -11
- package/.agents/scripts/lib/codebase-snapshot.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/sync-agentrc.js +1 -1
- package/.agents/scripts/lib/config/temp-paths.js +2 -2
- package/.agents/scripts/lib/config-settings-schema-delivery.js +2 -2
- package/.agents/scripts/lib/config-settings-schema-quality.js +1 -1
- package/.agents/scripts/lib/config-settings-schema.js +3 -3
- package/.agents/scripts/lib/detect-package-manager.js +72 -0
- package/.agents/scripts/lib/duplicate-search.js +1 -1
- package/.agents/scripts/lib/dynamic-workflow/capability.js +1 -1
- package/.agents/scripts/lib/epic-plan-clarity.js +1 -1
- package/.agents/scripts/lib/epic-plan-ideation.js +1 -1
- package/.agents/scripts/lib/errors/index.js +4 -4
- package/.agents/scripts/lib/feedback-loop/memory-freshness.js +1 -1
- package/.agents/scripts/lib/feedback-loop/prior-feedback-fetcher.js +1 -1
- package/.agents/scripts/lib/findings/classify-finding.js +1 -1
- package/.agents/scripts/lib/findings/promote-finding.js +10 -10
- package/.agents/scripts/lib/label-constants.js +3 -4
- package/.agents/scripts/lib/label-taxonomy.js +5 -10
- package/.agents/scripts/lib/onboard/detect-stack.js +10 -10
- package/.agents/scripts/lib/onboard/init-tail.js +218 -0
- package/.agents/scripts/lib/onboard/scaffold-docs.js +18 -3
- package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +1 -1
- package/.agents/scripts/lib/orchestration/code-review.js +5 -5
- package/.agents/scripts/lib/orchestration/context-hydration-engine.js +8 -9
- package/.agents/scripts/lib/orchestration/dependency-analyzer.js +3 -3
- package/.agents/scripts/lib/orchestration/detectors-phase.js +2 -2
- package/.agents/scripts/lib/orchestration/dispatch-engine.js +30 -38
- package/.agents/scripts/lib/orchestration/dispatch-pipeline.js +9 -25
- package/.agents/scripts/lib/orchestration/epic-cleanup.js +1 -1
- package/.agents/scripts/lib/orchestration/epic-deliver-lease-guard.js +8 -8
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/creation.js +1 -1
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/dag.js +7 -21
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/diagnostics.js +3 -3
- package/.agents/scripts/lib/orchestration/epic-plan-lease-guard.js +26 -13
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/plan-epic.js +1 -1
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/prompts.js +1 -1
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/run-spec-phase.js +2 -2
- package/.agents/scripts/lib/orchestration/epic-plan-state-store.js +1 -1
- package/.agents/scripts/lib/orchestration/epic-run-state-store.js +3 -3
- package/.agents/scripts/lib/orchestration/epic-runner/concurrency-gate.js +4 -4
- package/.agents/scripts/lib/orchestration/epic-runner/deliver-phases.js +3 -3
- package/.agents/scripts/lib/orchestration/epic-runner/phases/build-wave-dag.js +6 -21
- package/.agents/scripts/lib/orchestration/epic-runner/phases/snapshot.js +7 -7
- package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/composition.js +1 -1
- package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/signals.js +2 -2
- package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/transport.js +4 -4
- package/.agents/scripts/lib/orchestration/epic-runner/story-launcher.js +4 -4
- package/.agents/scripts/lib/orchestration/epic-runner/story-run-progress-writer.js +8 -8
- package/.agents/scripts/lib/orchestration/epic-runner/sub-agent-return.js +4 -4
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-apply.js +7 -15
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-diff.js +72 -41
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-ops.js +2 -4
- package/.agents/scripts/lib/orchestration/file-assumptions.js +2 -2
- package/.agents/scripts/lib/orchestration/finalize/close-planning-tickets.js +1 -1
- package/.agents/scripts/lib/orchestration/finalize/open-or-locate-pr.js +2 -2
- package/.agents/scripts/lib/orchestration/finalize/sanitize-skip-ci.js +1 -1
- package/.agents/scripts/lib/orchestration/lease-guard-shared.js +3 -3
- package/.agents/scripts/lib/orchestration/lifecycle/emit-story-dispatch-end.js +1 -1
- package/.agents/scripts/lib/orchestration/lifecycle/emit-story-heartbeat.js +1 -1
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +1 -1
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-armer.js +1 -1
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-predicate.js +1 -1
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/branch-cleaner.js +1 -1
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/finalizer.js +1 -1
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/index.js +1 -1
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/merge-watcher.js +1 -1
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/notify-dispatcher.js +1 -1
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/watcher.js +1 -1
- package/.agents/scripts/lib/orchestration/manifest-builder.js +5 -5
- package/.agents/scripts/lib/orchestration/parked-follow-ons.js +2 -2
- package/.agents/scripts/lib/orchestration/plan-runner/plan-router.js +5 -5
- package/.agents/scripts/lib/orchestration/post-merge/phases/ticket-closure.js +3 -3
- package/.agents/scripts/lib/orchestration/preflight-cache.js +1 -1
- package/.agents/scripts/lib/orchestration/recurring-failure-detector.js +1 -1
- package/.agents/scripts/lib/orchestration/retro/phases/compose-body.js +1 -1
- package/.agents/scripts/lib/orchestration/retro/phases/gather-signals.js +2 -2
- package/.agents/scripts/lib/orchestration/retro-runner.js +3 -3
- package/.agents/scripts/lib/orchestration/review-depth.js +1 -1
- package/.agents/scripts/lib/orchestration/single-story-close/phases/wrong-tree-guard.js +1 -1
- package/.agents/scripts/lib/orchestration/spec-freshness.js +1 -1
- package/.agents/scripts/lib/orchestration/spec-renderer.js +36 -73
- package/.agents/scripts/lib/orchestration/spec-section-validator.js +1 -1
- package/.agents/scripts/lib/orchestration/story-close/baseline-friction-body.js +1 -1
- package/.agents/scripts/lib/orchestration/story-close/phases/locked-pipeline.js +2 -2
- package/.agents/scripts/lib/orchestration/task-body-validator.js +6 -6
- package/.agents/scripts/lib/orchestration/ticket-lease.js +1 -1
- package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +2 -2
- package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +1 -10
- package/.agents/scripts/lib/orchestration/ticket-validator.js +25 -70
- package/.agents/scripts/lib/orchestration/ticketing/bulk.js +5 -12
- package/.agents/scripts/lib/orchestration/ticketing/reads.js +8 -8
- package/.agents/scripts/lib/orchestration/ticketing/state.js +3 -3
- package/.agents/scripts/lib/orchestration/wave-record-notifications.js +2 -2
- package/.agents/scripts/lib/orchestration/wave-record-projection.js +1 -1
- package/.agents/scripts/lib/plan-phase-cleanup.js +1 -1
- package/.agents/scripts/lib/preflight-runner.js +1 -1
- package/.agents/scripts/lib/presentation/dispatch-manifest-render.js +4 -5
- package/.agents/scripts/lib/presentation/manifest-builder.js +28 -34
- package/.agents/scripts/lib/presentation/manifest-formatter.js +3 -4
- package/.agents/scripts/lib/presentation/manifest-helpers.js +1 -1
- package/.agents/scripts/lib/presentation/manifest-procedures.js +4 -4
- package/.agents/scripts/lib/presentation/manifest-render-waves.js +4 -23
- package/.agents/scripts/lib/presentation/manifest-renderer.js +1 -1
- package/.agents/scripts/lib/presentation/manifest-story-views.js +2 -11
- package/.agents/scripts/lib/runtime-deps/preflight.js +6 -6
- package/.agents/scripts/lib/signals/schema.js +1 -1
- package/.agents/scripts/lib/spec/index.js +1 -1
- package/.agents/scripts/lib/spec/loader.js +2 -2
- package/.agents/scripts/lib/spec/state.js +7 -16
- package/.agents/scripts/lib/story-init/context-resolver.js +3 -3
- package/.agents/scripts/lib/story-init/state-transitioner.js +2 -2
- package/.agents/scripts/lib/story-init/task-graph-builder.js +7 -7
- package/.agents/scripts/lib/story-lifecycle.js +8 -8
- package/.agents/scripts/lib/story-plan.js +1 -1
- package/.agents/scripts/lib/templates/decomposer-prompts.js +59 -52
- package/.agents/scripts/lib/wave-runner/tick.js +1 -1
- package/.agents/scripts/lib/worktree/node-modules-strategy.js +5 -2
- package/.agents/scripts/lifecycle-emit-story-dispatch.js +1 -1
- package/.agents/scripts/lifecycle-emit.js +1 -1
- package/.agents/scripts/providers/github/board-add.js +1 -1
- package/.agents/scripts/providers/github/errors.js +1 -1
- package/.agents/scripts/providers/github/mappers.js +2 -2
- package/.agents/scripts/providers/github/tickets.js +4 -4
- package/.agents/scripts/resync-status-column.js +1 -1
- package/.agents/scripts/retro-run.js +2 -2
- package/.agents/scripts/run-lint.js +1 -1
- package/.agents/scripts/single-story-init.js +1 -1
- package/.agents/scripts/stories-wave-tick.js +5 -5
- package/.agents/scripts/story-close.js +1 -1
- package/.agents/scripts/story-init.js +13 -16
- package/.agents/scripts/story-phase.js +5 -5
- package/.agents/scripts/story-plan.js +3 -3
- package/.agents/scripts/sync-branch-from-base.js +1 -1
- package/.agents/scripts/validate-docs-freshness.js +1 -1
- package/.agents/scripts/wave-tick.js +1 -1
- package/.agents/skills/core/analyze-execution/SKILL.md +2 -2
- package/.agents/skills/core/epic-plan-consolidate/SKILL.md +21 -26
- package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +23 -56
- package/.agents/skills/core/epic-plan-spec-author/SKILL.md +4 -4
- package/.agents/skills/core/hydrate-context/SKILL.md +2 -2
- package/.agents/skills/core/idea-refinement/SKILL.md +4 -4
- package/.agents/skills/core/knowledge-transfer/SKILL.md +2 -2
- package/.agents/skills/core/planning-and-task-breakdown/SKILL.md +1 -1
- package/.agents/skills/core/scope-triage/SKILL.md +9 -10
- package/.agents/skills/core/using-agent-skills/SKILL.md +1 -1
- package/.agents/skills/skills.index.json +7 -7
- package/.agents/templates/agent-protocol.md +2 -2
- package/.agents/workflows/agents-update.md +16 -31
- package/.agents/workflows/audit-architecture.md +2 -2
- package/.agents/workflows/audit-clean-code.md +2 -2
- package/.agents/workflows/audit-dependencies.md +1 -1
- package/.agents/workflows/audit-devops.md +1 -1
- package/.agents/workflows/audit-documentation.md +2 -2
- package/.agents/workflows/audit-lighthouse.md +1 -1
- package/.agents/workflows/audit-performance.md +2 -2
- package/.agents/workflows/audit-privacy.md +1 -1
- package/.agents/workflows/audit-quality.md +2 -2
- package/.agents/workflows/audit-security.md +2 -2
- package/.agents/workflows/audit-seo.md +1 -1
- package/.agents/workflows/audit-sre.md +1 -1
- package/.agents/workflows/audit-to-stories.md +10 -10
- package/.agents/workflows/audit-ux-ui.md +1 -1
- package/.agents/workflows/deliver.md +85 -0
- package/.agents/workflows/explain.md +3 -3
- package/.agents/workflows/git-merge-pr.md +1 -1
- package/.agents/workflows/git-pr-all.md +13 -10
- package/.agents/workflows/git-push.md +6 -3
- package/.agents/workflows/helpers/_merge-conflict-template.md +1 -1
- package/.agents/workflows/helpers/acceptance-self-eval.md +1 -1
- package/.agents/workflows/helpers/agents-sync-config.md +3 -2
- package/.agents/workflows/helpers/code-review.md +5 -5
- package/.agents/workflows/{epic-deliver.md → helpers/deliver-epic.md} +43 -43
- package/.agents/workflows/{story-deliver.md → helpers/deliver-stories.md} +25 -25
- package/.agents/workflows/helpers/diagnose.md +1 -1
- package/.agents/workflows/helpers/epic-audit.md +6 -6
- package/.agents/workflows/helpers/epic-deliver-story.md +13 -13
- package/.agents/workflows/helpers/epic-plan-decompose.md +23 -23
- package/.agents/workflows/helpers/epic-plan-spec.md +6 -6
- package/.agents/workflows/helpers/epic-testing.md +3 -3
- package/.agents/workflows/helpers/parallel-tooling.md +1 -1
- package/.agents/workflows/{epic-plan.md → helpers/plan-epic.md} +84 -84
- package/.agents/workflows/{story-plan.md → helpers/plan-story.md} +43 -43
- package/.agents/workflows/helpers/signals.md +1 -1
- package/.agents/workflows/helpers/single-story-deliver.md +11 -11
- package/.agents/workflows/helpers/worktree-lifecycle.md +18 -18
- package/.agents/workflows/plan.md +131 -0
- package/.agents/workflows/qa-explore.md +1 -1
- package/.agents/workflows/qa-run-harness.md +1 -1
- package/README.md +19 -39
- package/bin/mandrel.js +235 -16
- package/docs/CHANGELOG.md +1173 -0
- package/lib/cli/doctor.js +45 -3
- package/lib/cli/init.js +97 -36
- package/lib/cli/registry.js +41 -145
- package/lib/cli/sync.js +122 -23
- package/lib/cli/uninstall.js +42 -7
- package/lib/cli/update.js +524 -210
- package/lib/cli/version-helpers.js +59 -0
- package/package.json +7 -6
- package/.agents/scripts/lib/orchestration/reconciler.js +0 -137
- package/.agents/workflows/onboard.md +0 -208
- package/lib/cli/__tests__/migrate.test.js +0 -268
- package/lib/cli/__tests__/sync-local-zone.test.js +0 -247
- package/lib/cli/__tests__/sync.test.js +0 -372
- package/lib/cli/__tests__/update-major.test.js +0 -217
- package/lib/cli/__tests__/update.test.js +0 -696
- package/lib/cli/__tests__/version-check.test.js +0 -398
- package/lib/migrations/__tests__/index.test.js +0 -216
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// lib/cli/version-helpers.js
|
|
2
|
+
/**
|
|
3
|
+
* Shared semver-ish parse and compare helpers used by both
|
|
4
|
+
* `lib/cli/update.js` and `lib/cli/registry.js`.
|
|
5
|
+
*
|
|
6
|
+
* Both files previously defined local copies of `parseVersion` and
|
|
7
|
+
* `compareVersions`; this module is the single authoritative
|
|
8
|
+
* implementation (Story #4048 B3 — multiplied helpers).
|
|
9
|
+
*
|
|
10
|
+
* Builtins only — this module is imported from both the CLI surface
|
|
11
|
+
* (`lib/cli/`) and the doctor registry which runs before third-party
|
|
12
|
+
* packages are guaranteed to be present.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Parse a dotted semver-ish string into a numeric tuple. Non-numeric or
|
|
17
|
+
* missing segments coerce to 0 so a partial version still compares sanely.
|
|
18
|
+
*
|
|
19
|
+
* @param {string} version
|
|
20
|
+
* @returns {[number, number, number]}
|
|
21
|
+
*/
|
|
22
|
+
export function parseVersion(version) {
|
|
23
|
+
const [major, minor, patch] = String(version).split('.');
|
|
24
|
+
return [
|
|
25
|
+
Number.parseInt(major, 10) || 0,
|
|
26
|
+
Number.parseInt(minor, 10) || 0,
|
|
27
|
+
Number.parseInt(patch, 10) || 0,
|
|
28
|
+
];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Compare two version strings. Negative when `a < b`, zero when equal,
|
|
33
|
+
* positive when `a > b` (the standard `Array.sort` comparator contract).
|
|
34
|
+
*
|
|
35
|
+
* @param {string} a
|
|
36
|
+
* @param {string} b
|
|
37
|
+
* @returns {number}
|
|
38
|
+
*/
|
|
39
|
+
export function compareVersions(a, b) {
|
|
40
|
+
const pa = parseVersion(a);
|
|
41
|
+
const pb = parseVersion(b);
|
|
42
|
+
for (let i = 0; i < 3; i += 1) {
|
|
43
|
+
if (pa[i] !== pb[i]) return pa[i] - pb[i];
|
|
44
|
+
}
|
|
45
|
+
return 0;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* True when `target`'s major axis is strictly greater than `current`'s —
|
|
50
|
+
* the gated "crosses a major boundary" condition used by the update
|
|
51
|
+
* orchestrator.
|
|
52
|
+
*
|
|
53
|
+
* @param {string} current
|
|
54
|
+
* @param {string} target
|
|
55
|
+
* @returns {boolean}
|
|
56
|
+
*/
|
|
57
|
+
export function crossesMajor(current, target) {
|
|
58
|
+
return parseVersion(target)[0] > parseVersion(current)[0];
|
|
59
|
+
}
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mandrel",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.61.0",
|
|
4
4
|
"description": "Claude Code-first opinionated workflow framework: instructions, personas, skills, and SDLC workflows that govern AI coding assistants.",
|
|
5
|
-
"main": "index.js",
|
|
6
5
|
"files": [
|
|
7
6
|
".agents/",
|
|
8
7
|
"bin/",
|
|
9
|
-
"
|
|
8
|
+
"docs/CHANGELOG.md",
|
|
9
|
+
"lib/",
|
|
10
|
+
"!lib/**/__tests__"
|
|
10
11
|
],
|
|
11
12
|
"publishConfig": {
|
|
12
13
|
"access": "public",
|
|
@@ -83,7 +84,8 @@
|
|
|
83
84
|
"knip": "^6.14.0",
|
|
84
85
|
"lint-staged": "^17.0.4",
|
|
85
86
|
"markdownlint-cli2": "^0.18.1",
|
|
86
|
-
"memfs": "^4.57.2"
|
|
87
|
+
"memfs": "^4.57.2",
|
|
88
|
+
"typescript": ">=5.0.0"
|
|
87
89
|
},
|
|
88
90
|
"dependencies": {
|
|
89
91
|
"ajv": "^8.20.0",
|
|
@@ -92,7 +94,6 @@
|
|
|
92
94
|
"minimatch": "^10.0.0",
|
|
93
95
|
"picomatch": "^4.0.4",
|
|
94
96
|
"string-argv": "^0.3.2",
|
|
95
|
-
"typescript": ">=5.0.0",
|
|
96
97
|
"typhonjs-escomplex": "^0.1.0"
|
|
97
98
|
},
|
|
98
99
|
"peerDependencies": {
|
|
@@ -100,7 +101,7 @@
|
|
|
100
101
|
},
|
|
101
102
|
"peerDependenciesMeta": {
|
|
102
103
|
"typescript": {
|
|
103
|
-
"optional":
|
|
104
|
+
"optional": true
|
|
104
105
|
}
|
|
105
106
|
}
|
|
106
107
|
}
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* lib/orchestration/reconciler.js — Ticket Hierarchy Reconciliation
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { Logger } from '../Logger.js';
|
|
6
|
-
import { AGENT_LABELS, TYPE_LABELS } from '../label-constants.js';
|
|
7
|
-
import { concurrentMap } from '../util/concurrent-map.js';
|
|
8
|
-
import { STATE_LABELS } from './ticketing.js';
|
|
9
|
-
|
|
10
|
-
const AGENT_DONE_LABEL = STATE_LABELS.DONE;
|
|
11
|
-
|
|
12
|
-
// Inlined parent-id parser. The reconciler only needs the direct parent
|
|
13
|
-
// reference scraped from a ticket body's `parent: #N` trailer; pulling the
|
|
14
|
-
// helper inline keeps reconciler.js self-contained for the 3-tier
|
|
15
|
-
// hierarchy walk (Stories → Features).
|
|
16
|
-
const PARENT_ID_PATTERN = /^parent:\s*#(\d+)/m;
|
|
17
|
-
|
|
18
|
-
function parseParentIdFromBody(body) {
|
|
19
|
-
const match = (body ?? '').match(PARENT_ID_PATTERN);
|
|
20
|
-
return match ? Number.parseInt(match[1], 10) : null;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// Cap=4 — bounded parallelism for ticket-update fan-outs. Reconciliation
|
|
24
|
-
// iterates an Epic-sized set of independent GitHub mutations; cap matches
|
|
25
|
-
// the established pattern across the orchestration layer (wave-gate,
|
|
26
|
-
// progress-reporter, sub-issue link reconcile) and stays well under the
|
|
27
|
-
// secondary rate-limit ceiling observed for issue PATCHes.
|
|
28
|
-
const RECONCILE_CONCURRENCY = 4;
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Reconcile the ticket hierarchy bottom-up (Stories → Features).
|
|
32
|
-
*
|
|
33
|
-
* Walks every Story and Feature under the Epic; if all children of a
|
|
34
|
-
* container are done, closes the container and applies `agent::done`.
|
|
35
|
-
*
|
|
36
|
-
* Epic auto-closure is intentionally excluded — Epics close only through
|
|
37
|
-
* the formal `/epic-deliver` workflow.
|
|
38
|
-
*
|
|
39
|
-
* Per-ticket provider failures are logged and swallowed so a single bad
|
|
40
|
-
* ticket cannot halt reconciliation across the rest of the graph.
|
|
41
|
-
*
|
|
42
|
-
* @param {import('../ITicketingProvider.js').ITicketingProvider} provider Ticketing provider.
|
|
43
|
-
* @param {number} _epicId Epic id (reserved — currently unused; kept for call-site stability).
|
|
44
|
-
* @param {object} _epic Epic ticket record (reserved — currently unused).
|
|
45
|
-
* @param {object[]} allTickets Every ticket under the Epic.
|
|
46
|
-
* @param {boolean} dryRun When true, mutate nothing.
|
|
47
|
-
* @returns {Promise<void>}
|
|
48
|
-
*/
|
|
49
|
-
export async function reconcileHierarchy(
|
|
50
|
-
provider,
|
|
51
|
-
_epicId,
|
|
52
|
-
_epic,
|
|
53
|
-
allTickets,
|
|
54
|
-
dryRun,
|
|
55
|
-
) {
|
|
56
|
-
const ticketMap = new Map(allTickets.map((t) => [t.id, t]));
|
|
57
|
-
|
|
58
|
-
const childrenOf = new Map();
|
|
59
|
-
for (const ticket of allTickets) {
|
|
60
|
-
const parentId = parseParentIdFromBody(ticket.body);
|
|
61
|
-
if (parentId != null) {
|
|
62
|
-
if (!childrenOf.has(parentId)) childrenOf.set(parentId, []);
|
|
63
|
-
childrenOf.get(parentId).push(ticket.id);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function isDone(ticketId) {
|
|
68
|
-
const t = ticketMap.get(ticketId);
|
|
69
|
-
if (!t) return false;
|
|
70
|
-
return (
|
|
71
|
-
t.state === 'closed' ||
|
|
72
|
-
(t.labelSet ?? new Set(t.labels)).has(AGENT_DONE_LABEL)
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function shouldClose(id) {
|
|
77
|
-
const ticket = ticketMap.get(id);
|
|
78
|
-
if (!ticket || ticket.state === 'closed') return null;
|
|
79
|
-
const children = childrenOf.get(id) ?? [];
|
|
80
|
-
if (children.length === 0) return null;
|
|
81
|
-
if (!children.every((cid) => isDone(cid))) return null;
|
|
82
|
-
return ticket;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
async function applyClose(id, typeName, ticket) {
|
|
86
|
-
try {
|
|
87
|
-
await provider.updateTicket(id, {
|
|
88
|
-
labels: {
|
|
89
|
-
add: [AGENT_DONE_LABEL],
|
|
90
|
-
remove: [AGENT_LABELS.READY, AGENT_LABELS.EXECUTING],
|
|
91
|
-
},
|
|
92
|
-
state: 'closed',
|
|
93
|
-
state_reason: 'completed',
|
|
94
|
-
});
|
|
95
|
-
ticket.state = 'closed';
|
|
96
|
-
Logger.info(`✅ ${typeName} #${id} closed and marked agent::done.`);
|
|
97
|
-
} catch (err) {
|
|
98
|
-
Logger.warn(`Failed to close ${typeName} #${id}: ${err.message}`);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
async function maybeClose(id, typeName) {
|
|
103
|
-
const ticket = shouldClose(id);
|
|
104
|
-
if (!ticket) return;
|
|
105
|
-
Logger.info(
|
|
106
|
-
`All children of ${typeName} #${id} "${ticket.title}" are done. Closing...`,
|
|
107
|
-
);
|
|
108
|
-
if (dryRun) {
|
|
109
|
-
Logger.info(
|
|
110
|
-
`[DRY-RUN] Would close ${typeName} #${id} and set agent::done.`,
|
|
111
|
-
);
|
|
112
|
-
ticket.state = 'closed';
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
await applyClose(id, typeName, ticket);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const storyIds = allTickets
|
|
119
|
-
.filter((t) => (t.labelSet ?? new Set(t.labels)).has(TYPE_LABELS.STORY))
|
|
120
|
-
.map((t) => t.id);
|
|
121
|
-
const featureIds = allTickets
|
|
122
|
-
.filter((t) => (t.labelSet ?? new Set(t.labels)).has(TYPE_LABELS.FEATURE))
|
|
123
|
-
.map((t) => t.id);
|
|
124
|
-
|
|
125
|
-
// cap=4 — Stories are container leaves of this reconcile (their children
|
|
126
|
-
// are Tasks already settled by reconcileClosedTasks); independent close
|
|
127
|
-
// mutations can fan out without ordering. Features stay sequential because
|
|
128
|
-
// a Feature may parent another Feature, and bottom-up close depends on
|
|
129
|
-
// child-Feature state already being mutated in the same pass.
|
|
130
|
-
await concurrentMap(storyIds, (id) => maybeClose(id, 'Story'), {
|
|
131
|
-
concurrency: RECONCILE_CONCURRENCY,
|
|
132
|
-
});
|
|
133
|
-
for (const id of featureIds) await maybeClose(id, 'Feature');
|
|
134
|
-
|
|
135
|
-
// EXCLUSION: Epic auto-closure removed.
|
|
136
|
-
// The Epic ticket now stays open until the formal /epic-deliver workflow is executed.
|
|
137
|
-
}
|
|
@@ -1,208 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: >-
|
|
3
|
-
Guided first-run onboarding for a freshly installed Mandrel. Detects the
|
|
4
|
-
consumer stack, offers to scaffold any missing docsContextFiles, runs
|
|
5
|
-
`mandrel doctor` as a readiness gate, and hands off to a started /epic-plan.
|
|
6
|
-
The whole path is designed to take about 15 minutes from a clean checkout to
|
|
7
|
-
a planned Epic.
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
# /onboard
|
|
11
|
-
|
|
12
|
-
## Role
|
|
13
|
-
|
|
14
|
-
Onboarding guide. You walk a first-time operator from a freshly installed
|
|
15
|
-
Mandrel to their first planned Epic, composing the building blocks shipped by
|
|
16
|
-
the guided-onboard Feature (#3514): stack detection, docs scaffolding, the
|
|
17
|
-
`mandrel doctor` readiness check, and a started `/epic-plan` handoff.
|
|
18
|
-
|
|
19
|
-
## Overview
|
|
20
|
-
|
|
21
|
-
`/onboard` is the **guided first-successful-run path**. It sequences four
|
|
22
|
-
phases that each lean on an already-shipped, independently tested building
|
|
23
|
-
block, then hands the operator off to planning:
|
|
24
|
-
|
|
25
|
-
```text
|
|
26
|
-
/onboard
|
|
27
|
-
→ Phase 1 — Detect stack (lib/onboard/detect-stack.js#detectStack)
|
|
28
|
-
→ Phase 2 — Offer docs scaffolding (lib/onboard/scaffold-docs.js#scaffoldDocs)
|
|
29
|
-
→ Phase 3 — Readiness gate (mandrel doctor → lib/cli/doctor.js)
|
|
30
|
-
→ Phase 4 — Handoff to /epic-plan (started, not auto-run)
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
Each phase is **advisory and resumable**: re-running `/onboard` on an
|
|
34
|
-
already-onboarded project re-detects, re-checks, and offers the same handoff
|
|
35
|
-
without duplicating any scaffolding (the scaffolder only writes files that are
|
|
36
|
-
genuinely missing, and `mandrel doctor` is read-only).
|
|
37
|
-
|
|
38
|
-
### When to use `/onboard`
|
|
39
|
-
|
|
40
|
-
| Scenario | Command |
|
|
41
|
-
| --- | --- |
|
|
42
|
-
| First run after installing Mandrel into a project | `/onboard` |
|
|
43
|
-
| Plan a new Epic once onboarded | `/epic-plan <epicId>` or `/epic-plan --idea "<seed>"` |
|
|
44
|
-
| Deliver Epic-attached Stories | `/epic-deliver <epicId>` |
|
|
45
|
-
|
|
46
|
-
## Prerequisites
|
|
47
|
-
|
|
48
|
-
1. Mandrel installed and bootstrapped into the project. The zero-to-installed
|
|
49
|
-
path is `npx mandrel init`, which installs the `mandrel`
|
|
50
|
-
package (when absent), runs `mandrel sync` to materialize the `.agents/`
|
|
51
|
-
bundle, and then — on the **configure now** prompt option — execs
|
|
52
|
-
`.agents/scripts/bootstrap.js` to provision the project (labels,
|
|
53
|
-
board, `.agentrc.json` seed). `/onboard` runs **after** that bootstrap
|
|
54
|
-
completes — it does not invoke `bootstrap.js` itself, so the coupling is
|
|
55
|
-
indirect: bootstrap owns first-time provisioning, `/onboard` owns the
|
|
56
|
-
guided first-successful-run. By the time you reach `/onboard`, the
|
|
57
|
-
`.agents/` bundle is present and `mandrel` resolves on the `PATH`.
|
|
58
|
-
2. `GITHUB_TOKEN` available in the project's `.env` (Phase 3 checks this; the
|
|
59
|
-
token value is never echoed).
|
|
60
|
-
|
|
61
|
-
## The ~15-minute first-successful-run path
|
|
62
|
-
|
|
63
|
-
`/onboard` is tuned so a brand-new operator can go from a clean checkout to a
|
|
64
|
-
planned Epic in roughly **15 minutes**. The budget breaks down as:
|
|
65
|
-
|
|
66
|
-
| Step | Phase | Rough budget |
|
|
67
|
-
| --- | --- | --- |
|
|
68
|
-
| Detect the stack and confirm the report | Phase 1 | ~1 min |
|
|
69
|
-
| Review the missing-docs offer and accept the scaffold | Phase 2 | ~3 min |
|
|
70
|
-
| Run `mandrel doctor` and clear any ✘ checks | Phase 3 | ~5 min |
|
|
71
|
-
| Start `/epic-plan` and describe the first Epic idea | Phase 4 | ~6 min |
|
|
72
|
-
|
|
73
|
-
If any single phase blows its budget — most often a Phase 3 remedy such as
|
|
74
|
-
authenticating `gh` or installing runtime deps — clear that one check and
|
|
75
|
-
re-run `/onboard`; the earlier phases are cheap and idempotent, so re-running
|
|
76
|
-
costs seconds.
|
|
77
|
-
|
|
78
|
-
### Sample-repo pointer
|
|
79
|
-
|
|
80
|
-
If you do not have a project to onboard yet and just want to see the path
|
|
81
|
-
end-to-end, point `/onboard` at the **stack-detection sample-repo fixture**
|
|
82
|
-
that ships with the framework. `detectStack` is fixture-driven by design (its
|
|
83
|
-
filesystem facade reads a real directory), and the unit suite exercises it
|
|
84
|
-
against an on-disk sample repo — see
|
|
85
|
-
[`tests/onboard/detect-stack.test.js`](../../tests/onboard/detect-stack.test.js),
|
|
86
|
-
which builds a sample repo with a lockfile, a `package.json`, and source files
|
|
87
|
-
and asserts the detected package manager, test runner, and primary language.
|
|
88
|
-
Use that fixture (or any small throwaway repo with a `package.json` and a few
|
|
89
|
-
source files) as the target for a dry first run before onboarding a real
|
|
90
|
-
project.
|
|
91
|
-
|
|
92
|
-
## Phase 1 — Detect the stack
|
|
93
|
-
|
|
94
|
-
Inspect the consumer repository root and report what Mandrel inferred before
|
|
95
|
-
touching anything. Use the detection helper shipped by Story #3520:
|
|
96
|
-
|
|
97
|
-
```bash
|
|
98
|
-
node -e "import('./.agents/scripts/lib/onboard/detect-stack.js').then(m => console.log(JSON.stringify(m.detectStack(process.cwd()), null, 2)))"
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
`detectStack(root)` returns `{ packageManager, testRunner, primaryLanguage }`,
|
|
102
|
-
each inferred from on-disk signals (lockfiles, `package.json`, source-file
|
|
103
|
-
extensions) and `null` when no signal is found. Relay the report to the
|
|
104
|
-
operator so they can confirm Mandrel understood the project. Detection is
|
|
105
|
-
**read-only** — it never writes to disk — so a wrong guess is harmless and the
|
|
106
|
-
operator can simply correct course in their `.agentrc.json` later.
|
|
107
|
-
|
|
108
|
-
## Phase 2 — Offer to scaffold missing `docsContextFiles`
|
|
109
|
-
|
|
110
|
-
Mandrel agents perform a **mandatory read** of every file listed in
|
|
111
|
-
`project.docsContextFiles` before each task; a missing entry degrades every
|
|
112
|
-
downstream run. Detect which are absent and offer to scaffold stubs, using the
|
|
113
|
-
helper shipped by Story #3519:
|
|
114
|
-
|
|
115
|
-
1. **Preview (no writes).** Detect the missing set first:
|
|
116
|
-
|
|
117
|
-
```bash
|
|
118
|
-
node -e "import('./.agents/scripts/lib/onboard/scaffold-docs.js').then(m => console.log(JSON.stringify(m.scaffoldDocs({ write: false }), null, 2)))"
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
`scaffoldDocs({ write: false })` returns `{ docsRoot, docsContextFiles,
|
|
122
|
-
missing, present, created }` without creating any files.
|
|
123
|
-
|
|
124
|
-
2. **Offer.** Show the operator the `missing` list and ask whether to scaffold
|
|
125
|
-
stubs. If the list is empty, report "all docsContextFiles present" and skip
|
|
126
|
-
to Phase 3.
|
|
127
|
-
|
|
128
|
-
3. **Scaffold (on acceptance).** When the operator accepts, write the stubs:
|
|
129
|
-
|
|
130
|
-
```bash
|
|
131
|
-
node -e "import('./.agents/scripts/lib/onboard/scaffold-docs.js').then(m => console.log(JSON.stringify(m.scaffoldDocs({ write: true }), null, 2)))"
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
Each missing file is seeded from a dedicated template under
|
|
135
|
-
`.agents/templates/docs/<name>` when one ships, otherwise from a generic
|
|
136
|
-
placeholder stub. The operator replaces the stub content with real docs
|
|
137
|
-
later; the point of the scaffold is that the mandatory-read never resolves
|
|
138
|
-
to a missing file.
|
|
139
|
-
|
|
140
|
-
This phase is **idempotent**: the scaffolder only writes files that are
|
|
141
|
-
actually absent, so re-running `/onboard` after a partial scaffold creates
|
|
142
|
-
only the still-missing stubs.
|
|
143
|
-
|
|
144
|
-
## Phase 3 — Readiness gate (`mandrel doctor`)
|
|
145
|
-
|
|
146
|
-
Run the doctor as a **readiness gate** before handing off to planning:
|
|
147
|
-
|
|
148
|
-
```bash
|
|
149
|
-
mandrel doctor
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
`mandrel doctor` (see [`lib/cli/doctor.js`](../../lib/cli/doctor.js)) runs
|
|
153
|
-
every check in the registry in order — `node-version`, `git-available`,
|
|
154
|
-
`gh-available`, `github-token`, `gh-auth`, `commands-in-sync`, `runtime-deps`,
|
|
155
|
-
`agents-materialized`, `agents-drift`, `version-current` — and prints a
|
|
156
|
-
`✔`/`✘` line per check. Every failing check prints a `→ <remedy>` line, and
|
|
157
|
-
the command exits:
|
|
158
|
-
|
|
159
|
-
- **0** with `✅ Ready (N/N checks passed)` — proceed to Phase 4.
|
|
160
|
-
- **non-zero** with `❌ Not ready (M/N checks failed)` — **stop**. Work
|
|
161
|
-
through the `→` remedies (e.g. authenticate `gh`, set `GITHUB_TOKEN`,
|
|
162
|
-
install runtime deps), then re-run `mandrel doctor` until it is green.
|
|
163
|
-
|
|
164
|
-
Do **not** hand off to `/epic-plan` while the doctor is red — planning needs a
|
|
165
|
-
working `gh` / `GITHUB_TOKEN` and a materialized `.agents/` bundle, exactly
|
|
166
|
-
what the gate verifies. The `github-token` check never echoes the token value
|
|
167
|
-
(security baseline § Secrets Management).
|
|
168
|
-
|
|
169
|
-
## Phase 4 — Handoff to a started `/epic-plan`
|
|
170
|
-
|
|
171
|
-
With a green readiness gate, hand the operator off to planning. `/onboard`
|
|
172
|
-
**starts** the handoff — it surfaces the entry point and the idea-refinement
|
|
173
|
-
path — but does **not** auto-run `/epic-plan`, because Epic planning authors
|
|
174
|
-
GitHub artifacts and must stay under explicit operator control.
|
|
175
|
-
|
|
176
|
-
Present the operator with the two `/epic-plan` entry shapes:
|
|
177
|
-
|
|
178
|
-
- **From an idea** (no Epic exists yet):
|
|
179
|
-
|
|
180
|
-
```text
|
|
181
|
-
/epic-plan --idea "<one-line description of the first thing to build>"
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
This enters [`/epic-plan`](epic-plan.md) at Phase 1 (Idea Refinement),
|
|
185
|
-
which refines the seed into a PRD, Tech Spec, and a decomposed
|
|
186
|
-
Epic → Feature → Story backlog.
|
|
187
|
-
|
|
188
|
-
- **From an existing Epic** (a `type::epic` issue already exists):
|
|
189
|
-
|
|
190
|
-
```text
|
|
191
|
-
/epic-plan <epicId>
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
Stop here and let the operator invoke `/epic-plan` themselves. Once they have
|
|
195
|
-
a planned Epic, the natural next step is `/epic-deliver <epicId>` to execute
|
|
196
|
-
it — but that is beyond the onboarding path.
|
|
197
|
-
|
|
198
|
-
## Constraints
|
|
199
|
-
|
|
200
|
-
- **Read-before-write.** Phases 1 and 3 are read-only; Phase 2 writes only
|
|
201
|
-
files that are genuinely missing and only on explicit operator acceptance.
|
|
202
|
-
- **Do not auto-run `/epic-plan`.** Phase 4 starts the handoff; the operator
|
|
203
|
-
invokes planning. Planning authors GitHub artifacts and stays under human
|
|
204
|
-
control.
|
|
205
|
-
- **Never echo secrets.** The `github-token` check and any token-related
|
|
206
|
-
remedy must not print the token value.
|
|
207
|
-
- **Stop on a red doctor.** A non-zero `mandrel doctor` exit blocks the
|
|
208
|
-
handoff until the operator clears the failing checks.
|