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.
Files changed (267) hide show
  1. package/.agents/README.md +86 -44
  2. package/.agents/docs/SDLC.md +135 -141
  3. package/.agents/docs/configuration.md +77 -20
  4. package/.agents/docs/quality-gates.md +796 -0
  5. package/.agents/docs/workflows.md +6 -9
  6. package/.agents/instructions.md +12 -11
  7. package/.agents/personas/architect.md +1 -1
  8. package/.agents/personas/product.md +1 -1
  9. package/.agents/personas/project-manager.md +14 -14
  10. package/.agents/personas/technical-writer.md +1 -1
  11. package/.agents/rules/changelog-style.md +5 -5
  12. package/.agents/rules/git-conventions.md +3 -3
  13. package/.agents/runtime-deps.json +2 -2
  14. package/.agents/schemas/agentrc.schema.json +3 -3
  15. package/.agents/schemas/dispatch-manifest.json +4 -4
  16. package/.agents/schemas/epic-spec.schema.json +15 -45
  17. package/.agents/schemas/lifecycle/README.md +1 -1
  18. package/.agents/schemas/lifecycle/story.dispatch.end.schema.json +1 -1
  19. package/.agents/schemas/lifecycle/story.dispatch.start.schema.json +1 -1
  20. package/.agents/schemas/lifecycle/story.heartbeat.schema.json +1 -1
  21. package/.agents/schemas/validation-evidence.schema.json +1 -1
  22. package/.agents/scripts/README.md +2 -2
  23. package/.agents/scripts/acceptance-eval.js +1 -1
  24. package/.agents/scripts/acceptance-spec-reconciler.js +2 -2
  25. package/.agents/scripts/agents-bootstrap-github.js +23 -119
  26. package/.agents/scripts/analyze-execution.js +2 -2
  27. package/.agents/scripts/audit-to-stories.js +1 -1
  28. package/.agents/scripts/check-doc-links.js +2 -3
  29. package/.agents/scripts/diagnose-friction.js +1 -1
  30. package/.agents/scripts/dispatcher.js +2 -2
  31. package/.agents/scripts/drain-pending-cleanup.js +1 -1
  32. package/.agents/scripts/epic-audit-prepare.js +3 -3
  33. package/.agents/scripts/epic-deliver-note-intervention.js +2 -2
  34. package/.agents/scripts/epic-deliver-preflight.js +6 -6
  35. package/.agents/scripts/epic-deliver-prepare.js +1 -1
  36. package/.agents/scripts/epic-execute-record-wave.js +4 -4
  37. package/.agents/scripts/epic-plan-healthcheck.js +6 -10
  38. package/.agents/scripts/epic-plan-spec-validate.js +1 -1
  39. package/.agents/scripts/epic-reconcile.js +11 -29
  40. package/.agents/scripts/evidence-gate.js +1 -1
  41. package/.agents/scripts/generate-workflows-doc.js +1 -1
  42. package/.agents/scripts/hierarchy-gate.js +7 -11
  43. package/.agents/scripts/lib/ITicketingProvider.js +1 -1
  44. package/.agents/scripts/lib/audit-suite/selector.js +1 -1
  45. package/.agents/scripts/lib/audit-to-stories/seed-epic-from-findings.js +2 -2
  46. package/.agents/scripts/lib/baseline-snapshot.js +7 -7
  47. package/.agents/scripts/lib/bdd-runner-detect.js +1 -1
  48. package/.agents/scripts/lib/bdd-scenario-scanner.js +3 -3
  49. package/.agents/scripts/lib/bootstrap/baselines-layout-migration.js +1 -1
  50. package/.agents/scripts/lib/bootstrap/branch-protection.js +1 -1
  51. package/.agents/scripts/lib/bootstrap/ci-workflow-template.js +47 -1
  52. package/.agents/scripts/lib/bootstrap/commit-push.js +2 -2
  53. package/.agents/scripts/lib/bootstrap/gh-preflight.js +7 -9
  54. package/.agents/scripts/lib/bootstrap/manifest.js +21 -1
  55. package/.agents/scripts/lib/bootstrap/merge-methods.js +31 -16
  56. package/.agents/scripts/lib/bootstrap/project-bootstrap.js +32 -11
  57. package/.agents/scripts/lib/codebase-snapshot.js +1 -1
  58. package/.agents/scripts/lib/config/explain.js +1 -1
  59. package/.agents/scripts/lib/config/runners.js +2 -2
  60. package/.agents/scripts/lib/config/runtime.js +1 -1
  61. package/.agents/scripts/lib/config/sync-agentrc.js +1 -1
  62. package/.agents/scripts/lib/config/temp-paths.js +2 -2
  63. package/.agents/scripts/lib/config-settings-schema-delivery.js +2 -2
  64. package/.agents/scripts/lib/config-settings-schema-quality.js +1 -1
  65. package/.agents/scripts/lib/config-settings-schema.js +3 -3
  66. package/.agents/scripts/lib/detect-package-manager.js +72 -0
  67. package/.agents/scripts/lib/duplicate-search.js +1 -1
  68. package/.agents/scripts/lib/dynamic-workflow/capability.js +1 -1
  69. package/.agents/scripts/lib/epic-plan-clarity.js +1 -1
  70. package/.agents/scripts/lib/epic-plan-ideation.js +1 -1
  71. package/.agents/scripts/lib/errors/index.js +4 -4
  72. package/.agents/scripts/lib/feedback-loop/memory-freshness.js +1 -1
  73. package/.agents/scripts/lib/feedback-loop/prior-feedback-fetcher.js +1 -1
  74. package/.agents/scripts/lib/findings/classify-finding.js +1 -1
  75. package/.agents/scripts/lib/findings/promote-finding.js +10 -10
  76. package/.agents/scripts/lib/label-constants.js +3 -4
  77. package/.agents/scripts/lib/label-taxonomy.js +5 -10
  78. package/.agents/scripts/lib/onboard/detect-stack.js +10 -10
  79. package/.agents/scripts/lib/onboard/init-tail.js +218 -0
  80. package/.agents/scripts/lib/onboard/scaffold-docs.js +18 -3
  81. package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +1 -1
  82. package/.agents/scripts/lib/orchestration/code-review.js +5 -5
  83. package/.agents/scripts/lib/orchestration/context-hydration-engine.js +8 -9
  84. package/.agents/scripts/lib/orchestration/dependency-analyzer.js +3 -3
  85. package/.agents/scripts/lib/orchestration/detectors-phase.js +2 -2
  86. package/.agents/scripts/lib/orchestration/dispatch-engine.js +30 -38
  87. package/.agents/scripts/lib/orchestration/dispatch-pipeline.js +9 -25
  88. package/.agents/scripts/lib/orchestration/epic-cleanup.js +1 -1
  89. package/.agents/scripts/lib/orchestration/epic-deliver-lease-guard.js +8 -8
  90. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/creation.js +1 -1
  91. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/dag.js +7 -21
  92. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/diagnostics.js +3 -3
  93. package/.agents/scripts/lib/orchestration/epic-plan-lease-guard.js +26 -13
  94. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/plan-epic.js +1 -1
  95. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/prompts.js +1 -1
  96. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/run-spec-phase.js +2 -2
  97. package/.agents/scripts/lib/orchestration/epic-plan-state-store.js +1 -1
  98. package/.agents/scripts/lib/orchestration/epic-run-state-store.js +3 -3
  99. package/.agents/scripts/lib/orchestration/epic-runner/concurrency-gate.js +4 -4
  100. package/.agents/scripts/lib/orchestration/epic-runner/deliver-phases.js +3 -3
  101. package/.agents/scripts/lib/orchestration/epic-runner/phases/build-wave-dag.js +6 -21
  102. package/.agents/scripts/lib/orchestration/epic-runner/phases/snapshot.js +7 -7
  103. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/composition.js +1 -1
  104. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/signals.js +2 -2
  105. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/transport.js +4 -4
  106. package/.agents/scripts/lib/orchestration/epic-runner/story-launcher.js +4 -4
  107. package/.agents/scripts/lib/orchestration/epic-runner/story-run-progress-writer.js +8 -8
  108. package/.agents/scripts/lib/orchestration/epic-runner/sub-agent-return.js +4 -4
  109. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-apply.js +7 -15
  110. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-diff.js +72 -41
  111. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-ops.js +2 -4
  112. package/.agents/scripts/lib/orchestration/file-assumptions.js +2 -2
  113. package/.agents/scripts/lib/orchestration/finalize/close-planning-tickets.js +1 -1
  114. package/.agents/scripts/lib/orchestration/finalize/open-or-locate-pr.js +2 -2
  115. package/.agents/scripts/lib/orchestration/finalize/sanitize-skip-ci.js +1 -1
  116. package/.agents/scripts/lib/orchestration/lease-guard-shared.js +3 -3
  117. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-dispatch-end.js +1 -1
  118. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-heartbeat.js +1 -1
  119. package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +1 -1
  120. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-armer.js +1 -1
  121. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-predicate.js +1 -1
  122. package/.agents/scripts/lib/orchestration/lifecycle/listeners/branch-cleaner.js +1 -1
  123. package/.agents/scripts/lib/orchestration/lifecycle/listeners/finalizer.js +1 -1
  124. package/.agents/scripts/lib/orchestration/lifecycle/listeners/index.js +1 -1
  125. package/.agents/scripts/lib/orchestration/lifecycle/listeners/merge-watcher.js +1 -1
  126. package/.agents/scripts/lib/orchestration/lifecycle/listeners/notify-dispatcher.js +1 -1
  127. package/.agents/scripts/lib/orchestration/lifecycle/listeners/watcher.js +1 -1
  128. package/.agents/scripts/lib/orchestration/manifest-builder.js +5 -5
  129. package/.agents/scripts/lib/orchestration/parked-follow-ons.js +2 -2
  130. package/.agents/scripts/lib/orchestration/plan-runner/plan-router.js +5 -5
  131. package/.agents/scripts/lib/orchestration/post-merge/phases/ticket-closure.js +3 -3
  132. package/.agents/scripts/lib/orchestration/preflight-cache.js +1 -1
  133. package/.agents/scripts/lib/orchestration/recurring-failure-detector.js +1 -1
  134. package/.agents/scripts/lib/orchestration/retro/phases/compose-body.js +1 -1
  135. package/.agents/scripts/lib/orchestration/retro/phases/gather-signals.js +2 -2
  136. package/.agents/scripts/lib/orchestration/retro-runner.js +3 -3
  137. package/.agents/scripts/lib/orchestration/review-depth.js +1 -1
  138. package/.agents/scripts/lib/orchestration/single-story-close/phases/wrong-tree-guard.js +1 -1
  139. package/.agents/scripts/lib/orchestration/spec-freshness.js +1 -1
  140. package/.agents/scripts/lib/orchestration/spec-renderer.js +36 -73
  141. package/.agents/scripts/lib/orchestration/spec-section-validator.js +1 -1
  142. package/.agents/scripts/lib/orchestration/story-close/baseline-friction-body.js +1 -1
  143. package/.agents/scripts/lib/orchestration/story-close/phases/locked-pipeline.js +2 -2
  144. package/.agents/scripts/lib/orchestration/task-body-validator.js +6 -6
  145. package/.agents/scripts/lib/orchestration/ticket-lease.js +1 -1
  146. package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +2 -2
  147. package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +1 -10
  148. package/.agents/scripts/lib/orchestration/ticket-validator.js +25 -70
  149. package/.agents/scripts/lib/orchestration/ticketing/bulk.js +5 -12
  150. package/.agents/scripts/lib/orchestration/ticketing/reads.js +8 -8
  151. package/.agents/scripts/lib/orchestration/ticketing/state.js +3 -3
  152. package/.agents/scripts/lib/orchestration/wave-record-notifications.js +2 -2
  153. package/.agents/scripts/lib/orchestration/wave-record-projection.js +1 -1
  154. package/.agents/scripts/lib/plan-phase-cleanup.js +1 -1
  155. package/.agents/scripts/lib/preflight-runner.js +1 -1
  156. package/.agents/scripts/lib/presentation/dispatch-manifest-render.js +4 -5
  157. package/.agents/scripts/lib/presentation/manifest-builder.js +28 -34
  158. package/.agents/scripts/lib/presentation/manifest-formatter.js +3 -4
  159. package/.agents/scripts/lib/presentation/manifest-helpers.js +1 -1
  160. package/.agents/scripts/lib/presentation/manifest-procedures.js +4 -4
  161. package/.agents/scripts/lib/presentation/manifest-render-waves.js +4 -23
  162. package/.agents/scripts/lib/presentation/manifest-renderer.js +1 -1
  163. package/.agents/scripts/lib/presentation/manifest-story-views.js +2 -11
  164. package/.agents/scripts/lib/runtime-deps/preflight.js +6 -6
  165. package/.agents/scripts/lib/signals/schema.js +1 -1
  166. package/.agents/scripts/lib/spec/index.js +1 -1
  167. package/.agents/scripts/lib/spec/loader.js +2 -2
  168. package/.agents/scripts/lib/spec/state.js +7 -16
  169. package/.agents/scripts/lib/story-init/context-resolver.js +3 -3
  170. package/.agents/scripts/lib/story-init/state-transitioner.js +2 -2
  171. package/.agents/scripts/lib/story-init/task-graph-builder.js +7 -7
  172. package/.agents/scripts/lib/story-lifecycle.js +8 -8
  173. package/.agents/scripts/lib/story-plan.js +1 -1
  174. package/.agents/scripts/lib/templates/decomposer-prompts.js +59 -52
  175. package/.agents/scripts/lib/wave-runner/tick.js +1 -1
  176. package/.agents/scripts/lib/worktree/node-modules-strategy.js +5 -2
  177. package/.agents/scripts/lifecycle-emit-story-dispatch.js +1 -1
  178. package/.agents/scripts/lifecycle-emit.js +1 -1
  179. package/.agents/scripts/providers/github/board-add.js +1 -1
  180. package/.agents/scripts/providers/github/errors.js +1 -1
  181. package/.agents/scripts/providers/github/mappers.js +2 -2
  182. package/.agents/scripts/providers/github/tickets.js +4 -4
  183. package/.agents/scripts/resync-status-column.js +1 -1
  184. package/.agents/scripts/retro-run.js +2 -2
  185. package/.agents/scripts/run-lint.js +1 -1
  186. package/.agents/scripts/single-story-init.js +1 -1
  187. package/.agents/scripts/stories-wave-tick.js +5 -5
  188. package/.agents/scripts/story-close.js +1 -1
  189. package/.agents/scripts/story-init.js +13 -16
  190. package/.agents/scripts/story-phase.js +5 -5
  191. package/.agents/scripts/story-plan.js +3 -3
  192. package/.agents/scripts/sync-branch-from-base.js +1 -1
  193. package/.agents/scripts/validate-docs-freshness.js +1 -1
  194. package/.agents/scripts/wave-tick.js +1 -1
  195. package/.agents/skills/core/analyze-execution/SKILL.md +2 -2
  196. package/.agents/skills/core/epic-plan-consolidate/SKILL.md +21 -26
  197. package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +23 -56
  198. package/.agents/skills/core/epic-plan-spec-author/SKILL.md +4 -4
  199. package/.agents/skills/core/hydrate-context/SKILL.md +2 -2
  200. package/.agents/skills/core/idea-refinement/SKILL.md +4 -4
  201. package/.agents/skills/core/knowledge-transfer/SKILL.md +2 -2
  202. package/.agents/skills/core/planning-and-task-breakdown/SKILL.md +1 -1
  203. package/.agents/skills/core/scope-triage/SKILL.md +9 -10
  204. package/.agents/skills/core/using-agent-skills/SKILL.md +1 -1
  205. package/.agents/skills/skills.index.json +7 -7
  206. package/.agents/templates/agent-protocol.md +2 -2
  207. package/.agents/workflows/agents-update.md +16 -31
  208. package/.agents/workflows/audit-architecture.md +2 -2
  209. package/.agents/workflows/audit-clean-code.md +2 -2
  210. package/.agents/workflows/audit-dependencies.md +1 -1
  211. package/.agents/workflows/audit-devops.md +1 -1
  212. package/.agents/workflows/audit-documentation.md +2 -2
  213. package/.agents/workflows/audit-lighthouse.md +1 -1
  214. package/.agents/workflows/audit-performance.md +2 -2
  215. package/.agents/workflows/audit-privacy.md +1 -1
  216. package/.agents/workflows/audit-quality.md +2 -2
  217. package/.agents/workflows/audit-security.md +2 -2
  218. package/.agents/workflows/audit-seo.md +1 -1
  219. package/.agents/workflows/audit-sre.md +1 -1
  220. package/.agents/workflows/audit-to-stories.md +10 -10
  221. package/.agents/workflows/audit-ux-ui.md +1 -1
  222. package/.agents/workflows/deliver.md +85 -0
  223. package/.agents/workflows/explain.md +3 -3
  224. package/.agents/workflows/git-merge-pr.md +1 -1
  225. package/.agents/workflows/git-pr-all.md +13 -10
  226. package/.agents/workflows/git-push.md +6 -3
  227. package/.agents/workflows/helpers/_merge-conflict-template.md +1 -1
  228. package/.agents/workflows/helpers/acceptance-self-eval.md +1 -1
  229. package/.agents/workflows/helpers/agents-sync-config.md +3 -2
  230. package/.agents/workflows/helpers/code-review.md +5 -5
  231. package/.agents/workflows/{epic-deliver.md → helpers/deliver-epic.md} +43 -43
  232. package/.agents/workflows/{story-deliver.md → helpers/deliver-stories.md} +25 -25
  233. package/.agents/workflows/helpers/diagnose.md +1 -1
  234. package/.agents/workflows/helpers/epic-audit.md +6 -6
  235. package/.agents/workflows/helpers/epic-deliver-story.md +13 -13
  236. package/.agents/workflows/helpers/epic-plan-decompose.md +23 -23
  237. package/.agents/workflows/helpers/epic-plan-spec.md +6 -6
  238. package/.agents/workflows/helpers/epic-testing.md +3 -3
  239. package/.agents/workflows/helpers/parallel-tooling.md +1 -1
  240. package/.agents/workflows/{epic-plan.md → helpers/plan-epic.md} +84 -84
  241. package/.agents/workflows/{story-plan.md → helpers/plan-story.md} +43 -43
  242. package/.agents/workflows/helpers/signals.md +1 -1
  243. package/.agents/workflows/helpers/single-story-deliver.md +11 -11
  244. package/.agents/workflows/helpers/worktree-lifecycle.md +18 -18
  245. package/.agents/workflows/plan.md +131 -0
  246. package/.agents/workflows/qa-explore.md +1 -1
  247. package/.agents/workflows/qa-run-harness.md +1 -1
  248. package/README.md +19 -39
  249. package/bin/mandrel.js +235 -16
  250. package/docs/CHANGELOG.md +1173 -0
  251. package/lib/cli/doctor.js +45 -3
  252. package/lib/cli/init.js +97 -36
  253. package/lib/cli/registry.js +41 -145
  254. package/lib/cli/sync.js +122 -23
  255. package/lib/cli/uninstall.js +42 -7
  256. package/lib/cli/update.js +524 -210
  257. package/lib/cli/version-helpers.js +59 -0
  258. package/package.json +7 -6
  259. package/.agents/scripts/lib/orchestration/reconciler.js +0 -137
  260. package/.agents/workflows/onboard.md +0 -208
  261. package/lib/cli/__tests__/migrate.test.js +0 -268
  262. package/lib/cli/__tests__/sync-local-zone.test.js +0 -247
  263. package/lib/cli/__tests__/sync.test.js +0 -372
  264. package/lib/cli/__tests__/update-major.test.js +0 -217
  265. package/lib/cli/__tests__/update.test.js +0 -696
  266. package/lib/cli/__tests__/version-check.test.js +0 -398
  267. 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.59.0",
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
- "lib/"
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": false
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.