@isaacriehm/cairn-core 0.1.9 → 0.2.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 (158) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/context/checkpoint.d.ts +4 -3
  3. package/dist/context/checkpoint.js +4 -3
  4. package/dist/context/checkpoint.js.map +1 -1
  5. package/dist/context/index.d.ts +2 -2
  6. package/dist/context/index.js +2 -2
  7. package/dist/context/spec-delta.js +1 -1
  8. package/dist/context/spec-delta.js.map +1 -1
  9. package/dist/doctor/index.d.ts +1 -1
  10. package/dist/doctor/index.js +4 -59
  11. package/dist/doctor/index.js.map +1 -1
  12. package/dist/frontend-types.d.ts +3 -3
  13. package/dist/frontend-types.js +3 -3
  14. package/dist/gc/quality-update.d.ts +4 -4
  15. package/dist/gc/quality-update.js +4 -4
  16. package/dist/ground/manifest.js +0 -2
  17. package/dist/ground/manifest.js.map +1 -1
  18. package/dist/ground/paths.js +0 -1
  19. package/dist/ground/paths.js.map +1 -1
  20. package/dist/ground/scope-index.d.ts +3 -2
  21. package/dist/ground/scope-index.js +3 -2
  22. package/dist/ground/scope-index.js.map +1 -1
  23. package/dist/hooks/bypass-detection.js +13 -18
  24. package/dist/hooks/bypass-detection.js.map +1 -1
  25. package/dist/hooks/defer.d.ts +50 -0
  26. package/dist/hooks/defer.js +87 -0
  27. package/dist/hooks/defer.js.map +1 -0
  28. package/dist/hooks/index.d.ts +2 -0
  29. package/dist/hooks/index.js +1 -0
  30. package/dist/hooks/index.js.map +1 -1
  31. package/dist/hooks/post-tool-use/ledger-cache.d.ts +2 -2
  32. package/dist/hooks/post-tool-use/ledger-cache.js +5 -4
  33. package/dist/hooks/post-tool-use/ledger-cache.js.map +1 -1
  34. package/dist/hooks/runners/index.d.ts +2 -0
  35. package/dist/hooks/runners/index.js +1 -0
  36. package/dist/hooks/runners/index.js.map +1 -1
  37. package/dist/hooks/runners/session-start.js +49 -15
  38. package/dist/hooks/runners/session-start.js.map +1 -1
  39. package/dist/hooks/runners/stop.js +81 -24
  40. package/dist/hooks/runners/stop.js.map +1 -1
  41. package/dist/hooks/seed-attested.d.ts +25 -0
  42. package/dist/hooks/seed-attested.js +84 -0
  43. package/dist/hooks/seed-attested.js.map +1 -0
  44. package/dist/index.d.ts +2 -0
  45. package/dist/index.js +13 -7
  46. package/dist/index.js.map +1 -1
  47. package/dist/init/index.d.ts +2 -0
  48. package/dist/init/index.js +1 -0
  49. package/dist/init/index.js.map +1 -1
  50. package/dist/init/init.js +8 -90
  51. package/dist/init/init.js.map +1 -1
  52. package/dist/init/mapper.d.ts +1 -1
  53. package/dist/init/multi-dev/install.d.ts +15 -10
  54. package/dist/init/multi-dev/install.js +17 -14
  55. package/dist/init/multi-dev/install.js.map +1 -1
  56. package/dist/init/overlay.d.ts +14 -0
  57. package/dist/init/overlay.js +65 -0
  58. package/dist/init/overlay.js.map +1 -0
  59. package/dist/init/phases/1-detect.d.ts +10 -0
  60. package/dist/init/phases/1-detect.js +36 -0
  61. package/dist/init/phases/1-detect.js.map +1 -0
  62. package/dist/init/phases/10-strip.d.ts +11 -0
  63. package/dist/init/phases/10-strip.js +80 -0
  64. package/dist/init/phases/10-strip.js.map +1 -0
  65. package/dist/init/phases/12-multidev.d.ts +11 -0
  66. package/dist/init/phases/12-multidev.js +39 -0
  67. package/dist/init/phases/12-multidev.js.map +1 -0
  68. package/dist/init/phases/2-walker.d.ts +8 -0
  69. package/dist/init/phases/2-walker.js +34 -0
  70. package/dist/init/phases/2-walker.js.map +1 -0
  71. package/dist/init/phases/3-mapper.d.ts +14 -0
  72. package/dist/init/phases/3-mapper.js +56 -0
  73. package/dist/init/phases/3-mapper.js.map +1 -0
  74. package/dist/init/phases/3b-seed.d.ts +27 -0
  75. package/dist/init/phases/3b-seed.js +149 -0
  76. package/dist/init/phases/3b-seed.js.map +1 -0
  77. package/dist/init/phases/4-pilot.d.ts +10 -0
  78. package/dist/init/phases/4-pilot.js +70 -0
  79. package/dist/init/phases/4-pilot.js.map +1 -0
  80. package/dist/init/phases/5-brand.d.ts +10 -0
  81. package/dist/init/phases/5-brand.js +66 -0
  82. package/dist/init/phases/5-brand.js.map +1 -0
  83. package/dist/init/phases/6-docs-ingest.d.ts +11 -0
  84. package/dist/init/phases/6-docs-ingest.js +39 -0
  85. package/dist/init/phases/6-docs-ingest.js.map +1 -0
  86. package/dist/init/phases/7b-source-comments.d.ts +6 -0
  87. package/dist/init/phases/7b-source-comments.js +34 -0
  88. package/dist/init/phases/7b-source-comments.js.map +1 -0
  89. package/dist/init/phases/7c-rules-merge.d.ts +6 -0
  90. package/dist/init/phases/7c-rules-merge.js +34 -0
  91. package/dist/init/phases/7c-rules-merge.js.map +1 -0
  92. package/dist/init/phases/8-baseline.d.ts +10 -0
  93. package/dist/init/phases/8-baseline.js +52 -0
  94. package/dist/init/phases/8-baseline.js.map +1 -0
  95. package/dist/init/phases/index.d.ts +15 -0
  96. package/dist/init/phases/index.js +16 -0
  97. package/dist/init/phases/index.js.map +1 -0
  98. package/dist/init/phases/orchestrator.d.ts +49 -0
  99. package/dist/init/phases/orchestrator.js +85 -0
  100. package/dist/init/phases/orchestrator.js.map +1 -0
  101. package/dist/init/phases/state-io.d.ts +19 -0
  102. package/dist/init/phases/state-io.js +73 -0
  103. package/dist/init/phases/state-io.js.map +1 -0
  104. package/dist/init/phases/types.d.ts +93 -0
  105. package/dist/init/phases/types.js +30 -0
  106. package/dist/init/phases/types.js.map +1 -0
  107. package/dist/init/seed.js +11 -2
  108. package/dist/init/seed.js.map +1 -1
  109. package/dist/init/walker.d.ts +0 -6
  110. package/dist/init/walker.js +2 -3
  111. package/dist/init/walker.js.map +1 -1
  112. package/dist/join/index.js +49 -2
  113. package/dist/join/index.js.map +1 -1
  114. package/dist/logger.d.ts +1 -1
  115. package/dist/logger.js +5 -5
  116. package/dist/logger.js.map +1 -1
  117. package/dist/mcp/errors.d.ts +1 -1
  118. package/dist/mcp/schemas.d.ts +19 -0
  119. package/dist/mcp/schemas.js +19 -0
  120. package/dist/mcp/schemas.js.map +1 -1
  121. package/dist/mcp/tools/append-run-note.js +13 -6
  122. package/dist/mcp/tools/append-run-note.js.map +1 -1
  123. package/dist/mcp/tools/drop-task.js +1 -1
  124. package/dist/mcp/tools/drop-task.js.map +1 -1
  125. package/dist/mcp/tools/ground-get.js +2 -2
  126. package/dist/mcp/tools/ground-get.js.map +1 -1
  127. package/dist/mcp/tools/index.js +4 -0
  128. package/dist/mcp/tools/index.js.map +1 -1
  129. package/dist/mcp/tools/init-phases.d.ts +24 -0
  130. package/dist/mcp/tools/init-phases.js +140 -0
  131. package/dist/mcp/tools/init-phases.js.map +1 -0
  132. package/dist/mcp/tools/query-history.js +1 -1
  133. package/dist/mcp/tools/query-history.js.map +1 -1
  134. package/dist/mcp/tools/resolve-attention.d.ts +3 -1
  135. package/dist/mcp/tools/resolve-attention.js +228 -11
  136. package/dist/mcp/tools/resolve-attention.js.map +1 -1
  137. package/dist/profiles/types.d.ts +1 -1
  138. package/dist/sensors/catalog.js +8 -3
  139. package/dist/sensors/catalog.js.map +1 -1
  140. package/dist/session-start/build.d.ts +4 -0
  141. package/dist/session-start/build.js +7 -0
  142. package/dist/session-start/build.js.map +1 -1
  143. package/dist/status-line/format.d.ts +10 -7
  144. package/dist/status-line/format.js +16 -14
  145. package/dist/status-line/format.js.map +1 -1
  146. package/dist/status-line/index.d.ts +0 -3
  147. package/dist/status-line/index.js.map +1 -1
  148. package/dist/status-line/reader.d.ts +1 -1
  149. package/dist/status-line/reader.js +2 -5
  150. package/dist/status-line/reader.js.map +1 -1
  151. package/dist/status-line/writer.d.ts +1 -9
  152. package/dist/status-line/writer.js +1 -12
  153. package/dist/status-line/writer.js.map +1 -1
  154. package/package.json +1 -1
  155. package/templates/.cairn/JOIN.md +3 -9
  156. package/templates/.cairn/git-hooks/commit-msg +14 -3
  157. package/templates/.cairn/git-hooks/pre-commit +22 -13
  158. package/templates/README.md +0 -24
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Phase 4-pilot — operator picks the seed module.
3
+ *
4
+ * The mapper's `pilot_module` field is the model's first guess; this
5
+ * phase surfaces it alongside the next 2 strongest `key_modules` so
6
+ * the operator can override. Picking the pilot determines which
7
+ * module's globs flow into `.cairn/config.yaml.project_globs` first.
8
+ */
9
+ import { advancePhase } from "./orchestrator.js";
10
+ const MAX_OPTIONS = 3;
11
+ export async function runPhase4Pilot(state) {
12
+ const mapper = state.outputs["3-mapper"];
13
+ if (mapper === undefined) {
14
+ return {
15
+ status: "error",
16
+ error: {
17
+ code: "missing-prereqs",
18
+ message: "Phase 4 needs phase 3-mapper output",
19
+ },
20
+ state,
21
+ };
22
+ }
23
+ // Operator already picked → consume + advance.
24
+ if (state.answer !== undefined && state.answer.length > 0) {
25
+ const next = {
26
+ ...state,
27
+ outputs: { ...state.outputs, "4-pilot": { picked: state.answer } },
28
+ answer: undefined,
29
+ };
30
+ return {
31
+ status: "complete",
32
+ nextPhase: "5-brand",
33
+ state: advancePhase(next),
34
+ };
35
+ }
36
+ const out = mapper.output;
37
+ const candidates = [];
38
+ // Pilot first.
39
+ if (out.pilot_module.length > 0) {
40
+ candidates.push({
41
+ id: out.pilot_module,
42
+ label: out.pilot_module,
43
+ detail: "Mapper's first pick",
44
+ });
45
+ }
46
+ // Top 2 key_modules other than pilot.
47
+ for (const km of out.key_modules) {
48
+ if (candidates.length >= MAX_OPTIONS)
49
+ break;
50
+ if (km.path === out.pilot_module)
51
+ continue;
52
+ candidates.push({
53
+ id: km.path,
54
+ label: km.path,
55
+ detail: km.purpose,
56
+ });
57
+ }
58
+ // Fallback if mapper produced nothing.
59
+ if (candidates.length === 0) {
60
+ candidates.push({ id: "ALL", label: "ALL", detail: "Whole repo as the pilot scope" });
61
+ }
62
+ const question = {
63
+ id: "4-pilot",
64
+ prompt: "Which module should Cairn seed first?",
65
+ options: candidates,
66
+ default: candidates[0].id,
67
+ };
68
+ return { status: "needs_input", question, state };
69
+ }
70
+ //# sourceMappingURL=4-pilot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"4-pilot.js","sourceRoot":"","sources":["../../../src/init/phases/4-pilot.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AASjD,MAAM,WAAW,GAAG,CAAC,CAAC;AAEtB,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,KAAiB;IACpD,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAA6B,CAAC;IACrE,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO;YACL,MAAM,EAAE,OAAO;YACf,KAAK,EAAE;gBACL,IAAI,EAAE,iBAAiB;gBACvB,OAAO,EAAE,qCAAqC;aAC/C;YACD,KAAK;SACN,CAAC;IACJ,CAAC;IAED,+CAA+C;IAC/C,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1D,MAAM,IAAI,GAAe;YACvB,GAAG,KAAK;YACR,OAAO,EAAE,EAAE,GAAG,KAAK,CAAC,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,EAAE;YAClE,MAAM,EAAE,SAAS;SAClB,CAAC;QACF,OAAO;YACL,MAAM,EAAE,UAAU;YAClB,SAAS,EAAE,SAAS;YACpB,KAAK,EAAE,YAAY,CAAC,IAAI,CAAC;SAC1B,CAAC;IACJ,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC;IAC1B,MAAM,UAAU,GAAkB,EAAE,CAAC;IACrC,eAAe;IACf,IAAI,GAAG,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChC,UAAU,CAAC,IAAI,CAAC;YACd,EAAE,EAAE,GAAG,CAAC,YAAY;YACpB,KAAK,EAAE,GAAG,CAAC,YAAY;YACvB,MAAM,EAAE,qBAAqB;SAC9B,CAAC,CAAC;IACL,CAAC;IACD,sCAAsC;IACtC,KAAK,MAAM,EAAE,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;QACjC,IAAI,UAAU,CAAC,MAAM,IAAI,WAAW;YAAE,MAAM;QAC5C,IAAI,EAAE,CAAC,IAAI,KAAK,GAAG,CAAC,YAAY;YAAE,SAAS;QAC3C,UAAU,CAAC,IAAI,CAAC;YACd,EAAE,EAAE,EAAE,CAAC,IAAI;YACX,KAAK,EAAE,EAAE,CAAC,IAAI;YACd,MAAM,EAAE,EAAE,CAAC,OAAO;SACnB,CAAC,CAAC;IACL,CAAC;IACD,uCAAuC;IACvC,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,+BAA+B,EAAE,CAAC,CAAC;IACxF,CAAC;IAED,MAAM,QAAQ,GAAkB;QAC9B,EAAE,EAAE,SAAS;QACb,MAAM,EAAE,uCAAuC;QAC/C,OAAO,EAAE,UAAU;QACnB,OAAO,EAAE,UAAU,CAAC,CAAC,CAAE,CAAC,EAAE;KAC3B,CAAC;IACF,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AACpD,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Phase 5-brand — adopt brand DEC drafts inline.
3
+ *
4
+ * Emits ONE A/B/C choice. `auto-fill` substitutes positioning + voice
5
+ * from the mapper's domain summary; `skip` leaves status: draft for
6
+ * later editing; `manual` hands off to the operator (drafts stay
7
+ * draft, summary surfaces the file paths to edit).
8
+ */
9
+ import type { PhaseResult, PhaseState } from "./types.js";
10
+ export declare function runPhase5Brand(state: PhaseState): Promise<PhaseResult>;
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Phase 5-brand — adopt brand DEC drafts inline.
3
+ *
4
+ * Emits ONE A/B/C choice. `auto-fill` substitutes positioning + voice
5
+ * from the mapper's domain summary; `skip` leaves status: draft for
6
+ * later editing; `manual` hands off to the operator (drafts stay
7
+ * draft, summary surfaces the file paths to edit).
8
+ */
9
+ import { applyBrandAnswers } from "../brand-setup.js";
10
+ import { advancePhase } from "./orchestrator.js";
11
+ export async function runPhase5Brand(state) {
12
+ // Pending operator answer → execute the chosen path.
13
+ if (state.answer !== undefined && state.answer.length > 0) {
14
+ const choice = state.answer;
15
+ let result = null;
16
+ if (choice === "auto-fill") {
17
+ const mapper = state.outputs["3-mapper"];
18
+ if (mapper !== undefined) {
19
+ const answers = {
20
+ whatItDoes: mapper.output.domain_summary,
21
+ mainUsers: "",
22
+ voice: "",
23
+ avoid: "",
24
+ };
25
+ result = applyBrandAnswers(state.repoRoot, answers);
26
+ }
27
+ }
28
+ const next = {
29
+ ...state,
30
+ outputs: {
31
+ ...state.outputs,
32
+ "5-brand": { choice, applied: result },
33
+ },
34
+ answer: undefined,
35
+ };
36
+ return {
37
+ status: "complete",
38
+ nextPhase: "6-docs-ingest",
39
+ state: advancePhase(next),
40
+ };
41
+ }
42
+ const question = {
43
+ id: "5-brand",
44
+ prompt: "Brand DEC drafts — how should Cairn populate them?",
45
+ options: [
46
+ {
47
+ id: "skip",
48
+ label: "skip — keep drafts blank",
49
+ detail: ".cairn/ground/brand/* stays status: draft",
50
+ },
51
+ {
52
+ id: "auto-fill",
53
+ label: "auto-fill from mapper summary",
54
+ detail: "positioning.md gets the mapper's summary, status flips to current",
55
+ },
56
+ {
57
+ id: "manual",
58
+ label: "manual — edit drafts first",
59
+ detail: "Drafts stay status: draft; you can populate them later",
60
+ },
61
+ ],
62
+ default: "skip",
63
+ };
64
+ return { status: "needs_input", question, state };
65
+ }
66
+ //# sourceMappingURL=5-brand.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"5-brand.js","sourceRoot":"","sources":["../../../src/init/phases/5-brand.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,iBAAiB,EAAqB,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAQjD,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,KAAiB;IACpD,qDAAqD;IACrD,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1D,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;QAC5B,IAAI,MAAM,GAAqD,IAAI,CAAC;QACpE,IAAI,MAAM,KAAK,WAAW,EAAE,CAAC;YAC3B,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAA6B,CAAC;YACrE,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,MAAM,OAAO,GAAiB;oBAC5B,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,cAAc;oBACxC,SAAS,EAAE,EAAE;oBACb,KAAK,EAAE,EAAE;oBACT,KAAK,EAAE,EAAE;iBACV,CAAC;gBACF,MAAM,GAAG,iBAAiB,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACtD,CAAC;QACH,CAAC;QACD,MAAM,IAAI,GAAe;YACvB,GAAG,KAAK;YACR,OAAO,EAAE;gBACP,GAAG,KAAK,CAAC,OAAO;gBAChB,SAAS,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE;aACvC;YACD,MAAM,EAAE,SAAS;SAClB,CAAC;QACF,OAAO;YACL,MAAM,EAAE,UAAU;YAClB,SAAS,EAAE,eAAe;YAC1B,KAAK,EAAE,YAAY,CAAC,IAAI,CAAC;SAC1B,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAkB;QAC9B,EAAE,EAAE,SAAS;QACb,MAAM,EAAE,oDAAoD;QAC5D,OAAO,EAAE;YACP;gBACE,EAAE,EAAE,MAAM;gBACV,KAAK,EAAE,0BAA0B;gBACjC,MAAM,EAAE,2CAA2C;aACpD;YACD;gBACE,EAAE,EAAE,WAAW;gBACf,KAAK,EAAE,+BAA+B;gBACtC,MAAM,EAAE,mEAAmE;aAC5E;YACD;gBACE,EAAE,EAAE,QAAQ;gBACZ,KAAK,EAAE,4BAA4B;gBACnC,MAAM,EAAE,wDAAwD;aACjE;SACF;QACD,OAAO,EAAE,MAAM;KAChB,CAAC;IACF,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AACpD,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Phase 6-docs-ingest — Haiku batch over README + docs/ → DEC drafts
3
+ * + canonical-map topics + voice rewrites.
4
+ *
5
+ * Wraps `runDocsIngestion`; no operator input. The skill driver
6
+ * surfaces the resulting `decDraftsWritten` count in the post-init
7
+ * summary so the operator knows how much pending attention they
8
+ * have.
9
+ */
10
+ import type { PhaseResult, PhaseState } from "./types.js";
11
+ export declare function runPhase6DocsIngest(state: PhaseState): Promise<PhaseResult>;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Phase 6-docs-ingest — Haiku batch over README + docs/ → DEC drafts
3
+ * + canonical-map topics + voice rewrites.
4
+ *
5
+ * Wraps `runDocsIngestion`; no operator input. The skill driver
6
+ * surfaces the resulting `decDraftsWritten` count in the post-init
7
+ * summary so the operator knows how much pending attention they
8
+ * have.
9
+ */
10
+ import { runDocsIngestion } from "../ingest-docs.js";
11
+ import { advancePhase } from "./orchestrator.js";
12
+ export async function runPhase6DocsIngest(state) {
13
+ try {
14
+ const result = await runDocsIngestion({
15
+ repoRoot: state.repoRoot,
16
+ });
17
+ const next = {
18
+ ...state,
19
+ outputs: { ...state.outputs, "6-docs-ingest": result },
20
+ };
21
+ return {
22
+ status: "complete",
23
+ nextPhase: "7b-source-comments",
24
+ state: advancePhase(next),
25
+ };
26
+ }
27
+ catch (err) {
28
+ return {
29
+ status: "error",
30
+ error: {
31
+ code: "docs-ingest-failed",
32
+ message: "Docs ingestion pipeline failed",
33
+ detail: err instanceof Error ? err.stack ?? err.message : String(err),
34
+ },
35
+ state,
36
+ };
37
+ }
38
+ }
39
+ //# sourceMappingURL=6-docs-ingest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"6-docs-ingest.js","sourceRoot":"","sources":["../../../src/init/phases/6-docs-ingest.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,gBAAgB,EAAwB,MAAM,mBAAmB,CAAC;AAC3E,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGjD,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,KAAiB;IACzD,IAAI,CAAC;QACH,MAAM,MAAM,GAAoB,MAAM,gBAAgB,CAAC;YACrD,QAAQ,EAAE,KAAK,CAAC,QAAQ;SACzB,CAAC,CAAC;QACH,MAAM,IAAI,GAAe;YACvB,GAAG,KAAK;YACR,OAAO,EAAE,EAAE,GAAG,KAAK,CAAC,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE;SACvD,CAAC;QACF,OAAO;YACL,MAAM,EAAE,UAAU;YAClB,SAAS,EAAE,oBAAoB;YAC/B,KAAK,EAAE,YAAY,CAAC,IAAI,CAAC;SAC1B,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,MAAM,EAAE,OAAO;YACf,KAAK,EAAE;gBACL,IAAI,EAAE,oBAAoB;gBAC1B,OAAO,EAAE,gCAAgC;gBACzC,MAAM,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;aACtE;YACD,KAAK;SACN,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Phase 7b-source-comments — walk every source file's docblock-class
3
+ * comment, classify via Haiku, write DEC drafts / invariant proposals.
4
+ */
5
+ import type { PhaseResult, PhaseState } from "./types.js";
6
+ export declare function runPhase7bSourceComments(state: PhaseState): Promise<PhaseResult>;
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Phase 7b-source-comments — walk every source file's docblock-class
3
+ * comment, classify via Haiku, write DEC drafts / invariant proposals.
4
+ */
5
+ import { runSourceCommentsIngestion, } from "../source-comments/index.js";
6
+ import { advancePhase } from "./orchestrator.js";
7
+ export async function runPhase7bSourceComments(state) {
8
+ try {
9
+ const result = await runSourceCommentsIngestion({
10
+ repoRoot: state.repoRoot,
11
+ });
12
+ const next = {
13
+ ...state,
14
+ outputs: { ...state.outputs, "7b-source-comments": result },
15
+ };
16
+ return {
17
+ status: "complete",
18
+ nextPhase: "7c-rules-merge",
19
+ state: advancePhase(next),
20
+ };
21
+ }
22
+ catch (err) {
23
+ return {
24
+ status: "error",
25
+ error: {
26
+ code: "source-comments-failed",
27
+ message: "Source-comment ingestion failed",
28
+ detail: err instanceof Error ? err.stack ?? err.message : String(err),
29
+ },
30
+ state,
31
+ };
32
+ }
33
+ }
34
+ //# sourceMappingURL=7b-source-comments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"7b-source-comments.js","sourceRoot":"","sources":["../../../src/init/phases/7b-source-comments.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,0BAA0B,GAE3B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGjD,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAAC,KAAiB;IAC9D,IAAI,CAAC;QACH,MAAM,MAAM,GAA+B,MAAM,0BAA0B,CAAC;YAC1E,QAAQ,EAAE,KAAK,CAAC,QAAQ;SACzB,CAAC,CAAC;QACH,MAAM,IAAI,GAAe;YACvB,GAAG,KAAK;YACR,OAAO,EAAE,EAAE,GAAG,KAAK,CAAC,OAAO,EAAE,oBAAoB,EAAE,MAAM,EAAE;SAC5D,CAAC;QACF,OAAO;YACL,MAAM,EAAE,UAAU;YAClB,SAAS,EAAE,gBAAgB;YAC3B,KAAK,EAAE,YAAY,CAAC,IAAI,CAAC;SAC1B,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,MAAM,EAAE,OAAO;YACf,KAAK,EAAE;gBACL,IAAI,EAAE,wBAAwB;gBAC9B,OAAO,EAAE,iCAAiC;gBAC1C,MAAM,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;aACtE;YACD,KAAK;SACN,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Phase 7c-rules-merge — walk CLAUDE.md / AGENTS.md / .claude/rules/*
3
+ * sections, classify via Haiku, propose net-new rules + flag conflicts.
4
+ */
5
+ import type { PhaseResult, PhaseState } from "./types.js";
6
+ export declare function runPhase7cRulesMerge(state: PhaseState): Promise<PhaseResult>;
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Phase 7c-rules-merge — walk CLAUDE.md / AGENTS.md / .claude/rules/*
3
+ * sections, classify via Haiku, propose net-new rules + flag conflicts.
4
+ */
5
+ import { runRulesMerge, } from "../rules-merge/index.js";
6
+ import { advancePhase } from "./orchestrator.js";
7
+ export async function runPhase7cRulesMerge(state) {
8
+ try {
9
+ const result = await runRulesMerge({
10
+ repoRoot: state.repoRoot,
11
+ });
12
+ const next = {
13
+ ...state,
14
+ outputs: { ...state.outputs, "7c-rules-merge": result },
15
+ };
16
+ return {
17
+ status: "complete",
18
+ nextPhase: "8-baseline",
19
+ state: advancePhase(next),
20
+ };
21
+ }
22
+ catch (err) {
23
+ return {
24
+ status: "error",
25
+ error: {
26
+ code: "rules-merge-failed",
27
+ message: "Rules merge failed",
28
+ detail: err instanceof Error ? err.stack ?? err.message : String(err),
29
+ },
30
+ state,
31
+ };
32
+ }
33
+ }
34
+ //# sourceMappingURL=7c-rules-merge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"7c-rules-merge.js","sourceRoot":"","sources":["../../../src/init/phases/7c-rules-merge.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,aAAa,GAEd,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGjD,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,KAAiB;IAC1D,IAAI,CAAC;QACH,MAAM,MAAM,GAAwB,MAAM,aAAa,CAAC;YACtD,QAAQ,EAAE,KAAK,CAAC,QAAQ;SACzB,CAAC,CAAC;QACH,MAAM,IAAI,GAAe;YACvB,GAAG,KAAK;YACR,OAAO,EAAE,EAAE,GAAG,KAAK,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE;SACxD,CAAC;QACF,OAAO;YACL,MAAM,EAAE,UAAU;YAClB,SAAS,EAAE,YAAY;YACvB,KAAK,EAAE,YAAY,CAAC,IAAI,CAAC;SAC1B,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,MAAM,EAAE,OAAO;YACf,KAAK,EAAE;gBACL,IAAI,EAAE,oBAAoB;gBAC1B,OAAO,EAAE,oBAAoB;gBAC7B,MAAM,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;aACtE;YACD,KAAK;SACN,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Phase 8-baseline — first sensor sweep against the synthetic
3
+ * full-tree diff. Stamps the audit row counts under outputs so the
4
+ * skill driver can summarize "N findings across M sensors".
5
+ *
6
+ * Reads the mapper's globs (route handlers, DTOs, etc.) from phase 3
7
+ * if available. Falls back to baseline-audit's defaults otherwise.
8
+ */
9
+ import type { PhaseResult, PhaseState } from "./types.js";
10
+ export declare function runPhase8Baseline(state: PhaseState): Promise<PhaseResult>;
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Phase 8-baseline — first sensor sweep against the synthetic
3
+ * full-tree diff. Stamps the audit row counts under outputs so the
4
+ * skill driver can summarize "N findings across M sensors".
5
+ *
6
+ * Reads the mapper's globs (route handlers, DTOs, etc.) from phase 3
7
+ * if available. Falls back to baseline-audit's defaults otherwise.
8
+ */
9
+ import { defaultBaselineLanguages, runBaselineAudit, } from "../baseline-audit.js";
10
+ import { advancePhase } from "./orchestrator.js";
11
+ export async function runPhase8Baseline(state) {
12
+ const detection = state.outputs["1-detect"];
13
+ const mapper = state.outputs["3-mapper"];
14
+ const globs = mapper
15
+ ? {
16
+ route_handler_globs: mapper.output.route_handler_globs,
17
+ dto_globs: mapper.output.dto_globs,
18
+ generator_source_globs: mapper.output.generator_source_globs,
19
+ high_stakes_globs: mapper.output.high_stakes_globs,
20
+ off_limits: mapper.output.off_limits_globs,
21
+ }
22
+ : {};
23
+ const languages = defaultBaselineLanguages((detection?.stack_signatures ?? []).map((s) => s.kind));
24
+ try {
25
+ const result = await runBaselineAudit({
26
+ repoRoot: state.repoRoot,
27
+ projectGlobs: globs,
28
+ languages,
29
+ });
30
+ const next = {
31
+ ...state,
32
+ outputs: { ...state.outputs, "8-baseline": result },
33
+ };
34
+ return {
35
+ status: "complete",
36
+ nextPhase: "10-strip",
37
+ state: advancePhase(next),
38
+ };
39
+ }
40
+ catch (err) {
41
+ return {
42
+ status: "error",
43
+ error: {
44
+ code: "baseline-failed",
45
+ message: "Baseline sensor sweep failed",
46
+ detail: err instanceof Error ? err.stack ?? err.message : String(err),
47
+ },
48
+ state,
49
+ };
50
+ }
51
+ }
52
+ //# sourceMappingURL=8-baseline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"8-baseline.js","sourceRoot":"","sources":["../../../src/init/phases/8-baseline.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,wBAAwB,EACxB,gBAAgB,GAEjB,MAAM,sBAAsB,CAAC;AAI9B,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGjD,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,KAAiB;IACvD,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAAgC,CAAC;IAC3E,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAA6B,CAAC;IACrE,MAAM,KAAK,GAAiB,MAAM;QAChC,CAAC,CAAC;YACE,mBAAmB,EAAE,MAAM,CAAC,MAAM,CAAC,mBAAmB;YACtD,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,SAAS;YAClC,sBAAsB,EAAE,MAAM,CAAC,MAAM,CAAC,sBAAsB;YAC5D,iBAAiB,EAAE,MAAM,CAAC,MAAM,CAAC,iBAAiB;YAClD,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,gBAAgB;SAC3C;QACH,CAAC,CAAC,EAAE,CAAC;IACP,MAAM,SAAS,GAAG,wBAAwB,CACxC,CAAC,SAAS,EAAE,gBAAgB,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAc,CAAC,CACjE,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,MAAM,GAAwB,MAAM,gBAAgB,CAAC;YACzD,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,YAAY,EAAE,KAAK;YACnB,SAAS;SACV,CAAC,CAAC;QACH,MAAM,IAAI,GAAe;YACvB,GAAG,KAAK;YACR,OAAO,EAAE,EAAE,GAAG,KAAK,CAAC,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE;SACpD,CAAC;QACF,OAAO;YACL,MAAM,EAAE,UAAU;YAClB,SAAS,EAAE,UAAU;YACrB,KAAK,EAAE,YAAY,CAAC,IAAI,CAAC;SAC1B,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,MAAM,EAAE,OAAO;YACf,KAAK,EAAE;gBACL,IAAI,EAAE,iBAAiB;gBACvB,OAAO,EAAE,8BAA8B;gBACvC,MAAM,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;aACtE;YACD,KAAK;SACN,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,15 @@
1
+ export { PHASE_IDS, type PhaseId, type PhaseState, type PhaseOutputs, type PhaseResult, type PhaseQuestion, type PhaseOption, type PhaseError, type ResumeReport, } from "./types.js";
2
+ export { INIT_STATE_PATH, phaseStateAbsPath, readPhaseState, writePhaseState, clearPhaseState, } from "./state-io.js";
3
+ export { freshPhaseState, resumePhases, nextPhaseAfter, advancePhase, } from "./orchestrator.js";
4
+ export { runPhase1Detect } from "./1-detect.js";
5
+ export { runPhase2Walker } from "./2-walker.js";
6
+ export { runPhase3Mapper } from "./3-mapper.js";
7
+ export { runPhase3bSeed } from "./3b-seed.js";
8
+ export { runPhase4Pilot } from "./4-pilot.js";
9
+ export { runPhase5Brand } from "./5-brand.js";
10
+ export { runPhase6DocsIngest } from "./6-docs-ingest.js";
11
+ export { runPhase7bSourceComments } from "./7b-source-comments.js";
12
+ export { runPhase7cRulesMerge } from "./7c-rules-merge.js";
13
+ export { runPhase8Baseline } from "./8-baseline.js";
14
+ export { runPhase10Strip } from "./10-strip.js";
15
+ export { runPhase12Multidev } from "./12-multidev.js";
@@ -0,0 +1,16 @@
1
+ export { PHASE_IDS, } from "./types.js";
2
+ export { INIT_STATE_PATH, phaseStateAbsPath, readPhaseState, writePhaseState, clearPhaseState, } from "./state-io.js";
3
+ export { freshPhaseState, resumePhases, nextPhaseAfter, advancePhase, } from "./orchestrator.js";
4
+ export { runPhase1Detect } from "./1-detect.js";
5
+ export { runPhase2Walker } from "./2-walker.js";
6
+ export { runPhase3Mapper } from "./3-mapper.js";
7
+ export { runPhase3bSeed } from "./3b-seed.js";
8
+ export { runPhase4Pilot } from "./4-pilot.js";
9
+ export { runPhase5Brand } from "./5-brand.js";
10
+ export { runPhase6DocsIngest } from "./6-docs-ingest.js";
11
+ export { runPhase7bSourceComments } from "./7b-source-comments.js";
12
+ export { runPhase7cRulesMerge } from "./7c-rules-merge.js";
13
+ export { runPhase8Baseline } from "./8-baseline.js";
14
+ export { runPhase10Strip } from "./10-strip.js";
15
+ export { runPhase12Multidev } from "./12-multidev.js";
16
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/init/phases/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,GASV,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,eAAe,GAChB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,eAAe,EACf,YAAY,EACZ,cAAc,EACd,YAAY,GACb,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Orchestrator entry points for the MCP-native init pipeline.
3
+ *
4
+ * `resumePhases(repoRoot)` is the single readable surface for the
5
+ * cairn-adopt skill — it reads any persisted state, returns the next
6
+ * phase id, and (for fresh starts) constructs the initial PhaseState.
7
+ *
8
+ * Phase functions live in sibling files (one per id, see types.ts
9
+ * PHASE_IDS). The orchestrator does not invoke them directly; the
10
+ * skill driver calls each phase's MCP tool with the state returned
11
+ * from `resumePhases` and threads results forward.
12
+ */
13
+ import { type PhaseId, type PhaseState, type ResumeReport } from "./types.js";
14
+ /**
15
+ * Construct the fresh state for a brand-new init run. No filesystem
16
+ * IO — the caller persists this via `writePhaseState` once phase
17
+ * 1-detect has created `.cairn/`.
18
+ */
19
+ export declare function freshPhaseState(repoRoot: string): PhaseState;
20
+ /**
21
+ * Read whatever init state is on disk for `repoRoot` and return the
22
+ * next phase the skill driver should invoke. If no state exists, the
23
+ * first phase becomes "ready".
24
+ *
25
+ * The persisted `state.currentPhase` IS the next phase to run:
26
+ * - On "complete", the phase function calls `advancePhase` to
27
+ * increment `currentPhase` to the successor before persisting.
28
+ * - On "needs_input", `currentPhase` stays put — the operator's
29
+ * answer feeds back into the same phase.
30
+ *
31
+ * The init-phases MCP tool clears the state file as soon as the final
32
+ * phase returns nextPhase=null, so a "done" report only fires when
33
+ * cleanup itself failed. We model that as "ready" pointing at the last
34
+ * phase id; the skill re-invokes (idempotent) and then clearPhaseState
35
+ * runs again.
36
+ */
37
+ export declare function resumePhases(repoRoot: string): ResumeReport;
38
+ /**
39
+ * Compute the phase id that follows `current` in PHASE_IDS, or null
40
+ * when `current` is already the last id. Pure function — useful from
41
+ * inside individual phase functions when stamping their PhaseResult.
42
+ */
43
+ export declare function nextPhaseAfter(current: PhaseId): PhaseId | null;
44
+ /**
45
+ * Advance `state.currentPhase` to the next phase id. Returns a new
46
+ * state; does not mutate the input. Used by phase functions when
47
+ * stamping a "complete" result that hands off to the next phase.
48
+ */
49
+ export declare function advancePhase(state: PhaseState): PhaseState;
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Orchestrator entry points for the MCP-native init pipeline.
3
+ *
4
+ * `resumePhases(repoRoot)` is the single readable surface for the
5
+ * cairn-adopt skill — it reads any persisted state, returns the next
6
+ * phase id, and (for fresh starts) constructs the initial PhaseState.
7
+ *
8
+ * Phase functions live in sibling files (one per id, see types.ts
9
+ * PHASE_IDS). The orchestrator does not invoke them directly; the
10
+ * skill driver calls each phase's MCP tool with the state returned
11
+ * from `resumePhases` and threads results forward.
12
+ */
13
+ import { PHASE_IDS } from "./types.js";
14
+ import { readPhaseState } from "./state-io.js";
15
+ /**
16
+ * Construct the fresh state for a brand-new init run. No filesystem
17
+ * IO — the caller persists this via `writePhaseState` once phase
18
+ * 1-detect has created `.cairn/`.
19
+ */
20
+ export function freshPhaseState(repoRoot) {
21
+ return {
22
+ repoRoot,
23
+ currentPhase: PHASE_IDS[0],
24
+ outputs: {},
25
+ startedAt: new Date().toISOString(),
26
+ schemaVersion: 1,
27
+ };
28
+ }
29
+ /**
30
+ * Read whatever init state is on disk for `repoRoot` and return the
31
+ * next phase the skill driver should invoke. If no state exists, the
32
+ * first phase becomes "ready".
33
+ *
34
+ * The persisted `state.currentPhase` IS the next phase to run:
35
+ * - On "complete", the phase function calls `advancePhase` to
36
+ * increment `currentPhase` to the successor before persisting.
37
+ * - On "needs_input", `currentPhase` stays put — the operator's
38
+ * answer feeds back into the same phase.
39
+ *
40
+ * The init-phases MCP tool clears the state file as soon as the final
41
+ * phase returns nextPhase=null, so a "done" report only fires when
42
+ * cleanup itself failed. We model that as "ready" pointing at the last
43
+ * phase id; the skill re-invokes (idempotent) and then clearPhaseState
44
+ * runs again.
45
+ */
46
+ export function resumePhases(repoRoot) {
47
+ const persisted = readPhaseState(repoRoot);
48
+ if (persisted === null) {
49
+ return {
50
+ status: "ready",
51
+ nextPhase: PHASE_IDS[0],
52
+ state: freshPhaseState(repoRoot),
53
+ };
54
+ }
55
+ return {
56
+ status: "ready",
57
+ nextPhase: persisted.currentPhase,
58
+ state: persisted,
59
+ };
60
+ }
61
+ /**
62
+ * Compute the phase id that follows `current` in PHASE_IDS, or null
63
+ * when `current` is already the last id. Pure function — useful from
64
+ * inside individual phase functions when stamping their PhaseResult.
65
+ */
66
+ export function nextPhaseAfter(current) {
67
+ const idx = PHASE_IDS.indexOf(current);
68
+ if (idx === -1)
69
+ return null;
70
+ if (idx === PHASE_IDS.length - 1)
71
+ return null;
72
+ return PHASE_IDS[idx + 1] ?? null;
73
+ }
74
+ /**
75
+ * Advance `state.currentPhase` to the next phase id. Returns a new
76
+ * state; does not mutate the input. Used by phase functions when
77
+ * stamping a "complete" result that hands off to the next phase.
78
+ */
79
+ export function advancePhase(state) {
80
+ const next = nextPhaseAfter(state.currentPhase);
81
+ if (next === null)
82
+ return state;
83
+ return { ...state, currentPhase: next, answer: undefined };
84
+ }
85
+ //# sourceMappingURL=orchestrator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../../src/init/phases/orchestrator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,SAAS,EAAoD,MAAM,YAAY,CAAC;AACzF,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC9C,OAAO;QACL,QAAQ;QACR,YAAY,EAAE,SAAS,CAAC,CAAC,CAAC;QAC1B,OAAO,EAAE,EAAE;QACX,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,aAAa,EAAE,CAAC;KACjB,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB;IAC3C,MAAM,SAAS,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;IAC3C,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;QACvB,OAAO;YACL,MAAM,EAAE,OAAO;YACf,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;YACvB,KAAK,EAAE,eAAe,CAAC,QAAQ,CAAC;SACjC,CAAC;IACJ,CAAC;IACD,OAAO;QACL,MAAM,EAAE,OAAO;QACf,SAAS,EAAE,SAAS,CAAC,YAAY;QACjC,KAAK,EAAE,SAAS;KACjB,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,OAAgB;IAC7C,MAAM,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC,IAAI,GAAG,KAAK,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAC5B,IAAI,GAAG,KAAK,SAAS,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAC9C,OAAO,SAAS,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC;AACpC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,KAAiB;IAC5C,MAAM,IAAI,GAAG,cAAc,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IAChD,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAChC,OAAO,EAAE,GAAG,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;AAC7D,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * State persistence for the MCP-native init pipeline.
3
+ *
4
+ * State lives at `.cairn/init-state.json` once that directory exists
5
+ * (after phase 1-detect creates it). Before that, no state file is
6
+ * written — `readPhaseState` returns null and the orchestrator starts
7
+ * fresh at "1-detect". After the final phase succeeds the state file
8
+ * is removed by `clearPhaseState`.
9
+ */
10
+ import { type PhaseState } from "./types.js";
11
+ /** Filename relative to repoRoot. */
12
+ export declare const INIT_STATE_PATH: string;
13
+ export declare function phaseStateAbsPath(repoRoot: string): string;
14
+ /** Read the on-disk init state. Returns null if missing or unreadable. */
15
+ export declare function readPhaseState(repoRoot: string): PhaseState | null;
16
+ /** Atomically write the init state. Creates `.cairn/` if needed. */
17
+ export declare function writePhaseState(state: PhaseState): string;
18
+ /** Remove the init state file. No-op if it doesn't exist. */
19
+ export declare function clearPhaseState(repoRoot: string): void;
@@ -0,0 +1,73 @@
1
+ /**
2
+ * State persistence for the MCP-native init pipeline.
3
+ *
4
+ * State lives at `.cairn/init-state.json` once that directory exists
5
+ * (after phase 1-detect creates it). Before that, no state file is
6
+ * written — `readPhaseState` returns null and the orchestrator starts
7
+ * fresh at "1-detect". After the final phase succeeds the state file
8
+ * is removed by `clearPhaseState`.
9
+ */
10
+ import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync, } from "node:fs";
11
+ import { dirname, join } from "node:path";
12
+ import { PHASE_IDS } from "./types.js";
13
+ /** Filename relative to repoRoot. */
14
+ export const INIT_STATE_PATH = join(".cairn", "init-state.json");
15
+ export function phaseStateAbsPath(repoRoot) {
16
+ return join(repoRoot, INIT_STATE_PATH);
17
+ }
18
+ /** Read the on-disk init state. Returns null if missing or unreadable. */
19
+ export function readPhaseState(repoRoot) {
20
+ const abs = phaseStateAbsPath(repoRoot);
21
+ if (!existsSync(abs))
22
+ return null;
23
+ let parsed;
24
+ try {
25
+ parsed = JSON.parse(readFileSync(abs, "utf8"));
26
+ }
27
+ catch {
28
+ return null;
29
+ }
30
+ if (!isPhaseState(parsed))
31
+ return null;
32
+ return parsed;
33
+ }
34
+ /** Atomically write the init state. Creates `.cairn/` if needed. */
35
+ export function writePhaseState(state) {
36
+ const abs = phaseStateAbsPath(state.repoRoot);
37
+ mkdirSync(dirname(abs), { recursive: true });
38
+ const tmp = `${abs}.tmp`;
39
+ writeFileSync(tmp, JSON.stringify(state, null, 2), "utf8");
40
+ // POSIX rename is atomic on the same filesystem (always true here:
41
+ // tmp + final are in the same .cairn/ dir).
42
+ renameSync(tmp, abs);
43
+ return abs;
44
+ }
45
+ /** Remove the init state file. No-op if it doesn't exist. */
46
+ export function clearPhaseState(repoRoot) {
47
+ rmSync(phaseStateAbsPath(repoRoot), { force: true });
48
+ }
49
+ function isPhaseId(v) {
50
+ return typeof v === "string" && PHASE_IDS.includes(v);
51
+ }
52
+ function isStringOrUndef(v) {
53
+ return v === undefined || typeof v === "string";
54
+ }
55
+ function isPhaseState(x) {
56
+ if (x === null || typeof x !== "object")
57
+ return false;
58
+ const o = x;
59
+ if (o["schemaVersion"] !== 1)
60
+ return false;
61
+ if (typeof o["repoRoot"] !== "string")
62
+ return false;
63
+ if (!isPhaseId(o["currentPhase"]))
64
+ return false;
65
+ if (typeof o["outputs"] !== "object" || o["outputs"] === null)
66
+ return false;
67
+ if (!isStringOrUndef(o["answer"]))
68
+ return false;
69
+ if (typeof o["startedAt"] !== "string")
70
+ return false;
71
+ return true;
72
+ }
73
+ //# sourceMappingURL=state-io.js.map