@momentiq/dark-factory-cli 1.1.0 → 2.1.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 (149) hide show
  1. package/README.md +86 -2
  2. package/dist/adapters/critic-result-schema.d.ts +14 -14
  3. package/dist/adapters/index.d.ts +1 -0
  4. package/dist/adapters/index.d.ts.map +1 -1
  5. package/dist/adapters/index.js +7 -0
  6. package/dist/adapters/index.js.map +1 -1
  7. package/dist/adapters/static-schema-lint.d.ts +68 -0
  8. package/dist/adapters/static-schema-lint.d.ts.map +1 -0
  9. package/dist/adapters/static-schema-lint.js +813 -0
  10. package/dist/adapters/static-schema-lint.js.map +1 -0
  11. package/dist/cli.d.ts +17 -1
  12. package/dist/cli.d.ts.map +1 -1
  13. package/dist/cli.js +313 -41
  14. package/dist/cli.js.map +1 -1
  15. package/dist/commands/findings.d.ts +6 -0
  16. package/dist/commands/findings.d.ts.map +1 -0
  17. package/dist/commands/findings.js +196 -0
  18. package/dist/commands/findings.js.map +1 -0
  19. package/dist/commands/onboard.d.ts +6 -0
  20. package/dist/commands/onboard.d.ts.map +1 -0
  21. package/dist/commands/onboard.js +111 -0
  22. package/dist/commands/onboard.js.map +1 -0
  23. package/dist/commands/skills.d.ts +6 -0
  24. package/dist/commands/skills.d.ts.map +1 -0
  25. package/dist/commands/skills.js +248 -0
  26. package/dist/commands/skills.js.map +1 -0
  27. package/dist/cycle-doc-validator/validate_cycle_doc.py +131 -60
  28. package/dist/doctor.d.ts +17 -0
  29. package/dist/doctor.d.ts.map +1 -1
  30. package/dist/doctor.js +107 -0
  31. package/dist/doctor.js.map +1 -1
  32. package/dist/evidence/docker-build.d.ts +6 -0
  33. package/dist/evidence/docker-build.d.ts.map +1 -0
  34. package/dist/evidence/docker-build.js +199 -0
  35. package/dist/evidence/docker-build.js.map +1 -0
  36. package/dist/evidence/index.d.ts +1 -0
  37. package/dist/evidence/index.d.ts.map +1 -1
  38. package/dist/evidence/index.js +6 -0
  39. package/dist/evidence/index.js.map +1 -1
  40. package/dist/index.d.ts +1 -0
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +4 -0
  43. package/dist/index.js.map +1 -1
  44. package/dist/mcp/server.d.ts.map +1 -1
  45. package/dist/mcp/server.js +2 -0
  46. package/dist/mcp/server.js.map +1 -1
  47. package/dist/mcp/tools/doctor.d.ts.map +1 -1
  48. package/dist/mcp/tools/doctor.js +5 -0
  49. package/dist/mcp/tools/doctor.js.map +1 -1
  50. package/dist/mcp/tools/review-bypass.d.ts.map +1 -1
  51. package/dist/mcp/tools/review-bypass.js +21 -0
  52. package/dist/mcp/tools/review-bypass.js.map +1 -1
  53. package/dist/mcp/tools/skills-install.d.ts +6 -0
  54. package/dist/mcp/tools/skills-install.d.ts.map +1 -0
  55. package/dist/mcp/tools/skills-install.js +260 -0
  56. package/dist/mcp/tools/skills-install.js.map +1 -0
  57. package/dist/mcp/tools/stats-gate.d.ts.map +1 -1
  58. package/dist/mcp/tools/stats-gate.js +63 -15
  59. package/dist/mcp/tools/stats-gate.js.map +1 -1
  60. package/dist/onboard/analyze.d.ts +7 -0
  61. package/dist/onboard/analyze.d.ts.map +1 -0
  62. package/dist/onboard/analyze.js +86 -0
  63. package/dist/onboard/analyze.js.map +1 -0
  64. package/dist/onboard/analyzer.d.ts +15 -0
  65. package/dist/onboard/analyzer.d.ts.map +1 -0
  66. package/dist/onboard/analyzer.js +52 -0
  67. package/dist/onboard/analyzer.js.map +1 -0
  68. package/dist/onboard/analyzers/ci.d.ts +3 -0
  69. package/dist/onboard/analyzers/ci.d.ts.map +1 -0
  70. package/dist/onboard/analyzers/ci.js +112 -0
  71. package/dist/onboard/analyzers/ci.js.map +1 -0
  72. package/dist/onboard/analyzers/docs.d.ts +3 -0
  73. package/dist/onboard/analyzers/docs.d.ts.map +1 -0
  74. package/dist/onboard/analyzers/docs.js +151 -0
  75. package/dist/onboard/analyzers/docs.js.map +1 -0
  76. package/dist/onboard/analyzers/git.d.ts +3 -0
  77. package/dist/onboard/analyzers/git.d.ts.map +1 -0
  78. package/dist/onboard/analyzers/git.js +87 -0
  79. package/dist/onboard/analyzers/git.js.map +1 -0
  80. package/dist/onboard/analyzers/lockfile.d.ts +3 -0
  81. package/dist/onboard/analyzers/lockfile.d.ts.map +1 -0
  82. package/dist/onboard/analyzers/lockfile.js +285 -0
  83. package/dist/onboard/analyzers/lockfile.js.map +1 -0
  84. package/dist/onboard/analyzers/manifest.d.ts +3 -0
  85. package/dist/onboard/analyzers/manifest.d.ts.map +1 -0
  86. package/dist/onboard/analyzers/manifest.js +228 -0
  87. package/dist/onboard/analyzers/manifest.js.map +1 -0
  88. package/dist/onboard/analyzers/tree.d.ts +3 -0
  89. package/dist/onboard/analyzers/tree.d.ts.map +1 -0
  90. package/dist/onboard/analyzers/tree.js +196 -0
  91. package/dist/onboard/analyzers/tree.js.map +1 -0
  92. package/dist/onboard/fixtures/replay-git-history.d.ts +20 -0
  93. package/dist/onboard/fixtures/replay-git-history.d.ts.map +1 -0
  94. package/dist/onboard/fixtures/replay-git-history.js +91 -0
  95. package/dist/onboard/fixtures/replay-git-history.js.map +1 -0
  96. package/dist/onboard/schema.d.ts +545 -0
  97. package/dist/onboard/schema.d.ts.map +1 -0
  98. package/dist/onboard/schema.js +142 -0
  99. package/dist/onboard/schema.js.map +1 -0
  100. package/dist/policy/gate.d.ts +1 -1
  101. package/dist/policy/gate.d.ts.map +1 -1
  102. package/dist/policy/gate.js +96 -12
  103. package/dist/policy/gate.js.map +1 -1
  104. package/dist/prompt.d.ts +1 -0
  105. package/dist/prompt.d.ts.map +1 -1
  106. package/dist/prompt.js +105 -1
  107. package/dist/prompt.js.map +1 -1
  108. package/dist/report.d.ts +106 -3
  109. package/dist/report.d.ts.map +1 -1
  110. package/dist/report.js +282 -10
  111. package/dist/report.js.map +1 -1
  112. package/dist/runner.d.ts +2 -0
  113. package/dist/runner.d.ts.map +1 -1
  114. package/dist/runner.js +86 -2
  115. package/dist/runner.js.map +1 -1
  116. package/dist/self-consistency.d.ts +144 -0
  117. package/dist/self-consistency.d.ts.map +1 -0
  118. package/dist/self-consistency.js +368 -0
  119. package/dist/self-consistency.js.map +1 -0
  120. package/dist/skills/config.d.ts +176 -0
  121. package/dist/skills/config.d.ts.map +1 -0
  122. package/dist/skills/config.js +251 -0
  123. package/dist/skills/config.js.map +1 -0
  124. package/dist/skills/index.d.ts +4 -0
  125. package/dist/skills/index.d.ts.map +1 -0
  126. package/dist/skills/index.js +8 -0
  127. package/dist/skills/index.js.map +1 -0
  128. package/dist/skills/install.d.ts +62 -0
  129. package/dist/skills/install.d.ts.map +1 -0
  130. package/dist/skills/install.js +315 -0
  131. package/dist/skills/install.js.map +1 -0
  132. package/dist/skills/template.d.ts +42 -0
  133. package/dist/skills/template.d.ts.map +1 -0
  134. package/dist/skills/template.js +95 -0
  135. package/dist/skills/template.js.map +1 -0
  136. package/dist/trusted-surface/rebind.d.ts.map +1 -1
  137. package/dist/trusted-surface/rebind.js +14 -1
  138. package/dist/trusted-surface/rebind.js.map +1 -1
  139. package/package.json +36 -2
  140. package/skills/README.md +89 -0
  141. package/skills/chief-engineer-blitz/SKILL.md.tmpl +443 -0
  142. package/skills/chief-engineer-blitz/skill.json +53 -0
  143. package/skills/chief-engineer-review/SKILL.md.tmpl +184 -0
  144. package/skills/chief-engineer-review/references/review-examples.md.tmpl +130 -0
  145. package/skills/chief-engineer-review/skill.json +67 -0
  146. package/skills/chief-engineer-review/templates/code-review-prompt.md.tmpl +111 -0
  147. package/skills/chief-engineer-review/templates/escalation-prompt.md.tmpl +56 -0
  148. package/skills/chief-engineer-review/templates/plan-review-prompt.md.tmpl +74 -0
  149. package/skills/skill-schema.json +73 -0
@@ -0,0 +1,86 @@
1
+ // analyze() orchestrator — cycle 15 Phase A.
2
+ //
3
+ // Pulls the 6 domain analyzers together, surfaces failures as a first-class
4
+ // `analyzerErrors` field (never silently dropped), enforces the 16 KB
5
+ // serialized-size budget as a final backstop, returns a Zod-validated
6
+ // RepoAnalysis.
7
+ import { runAnalyzers } from "./analyzer.js";
8
+ import { RepoAnalysisSchema, AGENT_CONTEXT_SCHEMA_VERSION, } from "./schema.js";
9
+ import { manifestAnalyzer } from "./analyzers/manifest.js";
10
+ import { lockfileAnalyzer } from "./analyzers/lockfile.js";
11
+ import { ciAnalyzer } from "./analyzers/ci.js";
12
+ import { treeAnalyzer } from "./analyzers/tree.js";
13
+ import { gitAnalyzer } from "./analyzers/git.js";
14
+ import { docsAnalyzer } from "./analyzers/docs.js";
15
+ const ALL_ANALYZERS = [
16
+ manifestAnalyzer,
17
+ lockfileAnalyzer,
18
+ ciAnalyzer,
19
+ treeAnalyzer,
20
+ gitAnalyzer,
21
+ docsAnalyzer,
22
+ ];
23
+ // The 16 KB serialized-size budget is a hard contract (cycle 15 D2 line 154,
24
+ // exit criterion "RepoAnalysis JSON of bounded size (≤ 16 KB)"). The per-array
25
+ // .max() caps on the Zod schema prevent the common overflow paths; this final
26
+ // enforcement is the backstop for unforeseen growth (giant headings, very long
27
+ // canonicalName, etc.) so a partial silent-truncation can never reach Phase B.
28
+ export const REPO_ANALYSIS_BYTE_BUDGET = 16_384;
29
+ function emptyBase(rootDir) {
30
+ return {
31
+ schemaVersion: AGENT_CONTEXT_SCHEMA_VERSION,
32
+ repoRoot: rootDir,
33
+ canonicalName: "",
34
+ stacks: [],
35
+ services: [],
36
+ dependencies: [],
37
+ ci: { workflows: [], deployStory: null },
38
+ tree: { topLevelDirs: [], languageBreakdown: {}, testDirs: [], fileCount: 0 },
39
+ git: {
40
+ recentCommitConventions: { conventional: false, cycleReferenced: false },
41
+ defaultBranch: "main",
42
+ },
43
+ docs: {
44
+ existing: [],
45
+ hasClaudeMd: false,
46
+ hasAgentsMd: false,
47
+ agentContextSetPresent: false,
48
+ claudeMd: null,
49
+ agentsMd: null,
50
+ },
51
+ dfPresence: { hooks: false, configJson: false, prWorkflow: false, cliPin: null },
52
+ decisions: [],
53
+ analyzerErrors: [],
54
+ };
55
+ }
56
+ export async function analyze(rootDir, analyzers = ALL_ANALYZERS) {
57
+ const merged = await runAnalyzers(rootDir, analyzers);
58
+ // Surface analyzer failures as a first-class schema field; never drop them.
59
+ // The orchestrator does NOT throw on per-analyzer errors — partial-result
60
+ // reporting is the contract — but the field's presence is the loud signal
61
+ // Phase B and CLI consumers branch on.
62
+ const { __analyzerErrors, ...rest } = merged;
63
+ const base = emptyBase(rootDir);
64
+ const combined = {
65
+ ...base,
66
+ ...rest,
67
+ // Each top-level object field needs explicit merge so partial analyzers
68
+ // don't blow away the defaults from emptyBase.
69
+ ci: { ...base.ci, ...(rest.ci ?? {}) },
70
+ tree: { ...base.tree, ...(rest.tree ?? {}) },
71
+ git: { ...base.git, ...(rest.git ?? {}) },
72
+ docs: { ...base.docs, ...(rest.docs ?? {}) },
73
+ dfPresence: { ...base.dfPresence, ...(rest.dfPresence ?? {}) },
74
+ analyzerErrors: __analyzerErrors ?? [],
75
+ };
76
+ const parsed = RepoAnalysisSchema.parse(combined);
77
+ const json = JSON.stringify(parsed);
78
+ if (json.length > REPO_ANALYSIS_BYTE_BUDGET) {
79
+ throw new Error(`RepoAnalysis exceeds ${REPO_ANALYSIS_BYTE_BUDGET}-byte budget: produced ${json.length} bytes. ` +
80
+ "Likely cause: oversized headings/decisions/dependencies; rerun against a bounded subset or " +
81
+ "tighten analyzer caps. (cycle 15 D2 / exit criterion)");
82
+ }
83
+ return parsed;
84
+ }
85
+ export { ALL_ANALYZERS };
86
+ //# sourceMappingURL=analyze.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze.js","sourceRoot":"","sources":["../../src/onboard/analyze.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { RepoAnalysis, AnalyzerError } from "./schema.js";
2
+ export interface Analyzer {
3
+ name: string;
4
+ /**
5
+ * Return `null` to opt out (e.g. no `package.json` → manifest analyzer's
6
+ * JS branch skips). Return a `Partial<RepoAnalysis>` to contribute fields;
7
+ * the orchestrator merges all contributions.
8
+ */
9
+ detect(rootDir: string): Promise<Partial<RepoAnalysis> | null>;
10
+ }
11
+ export type MergedAnalysis = Partial<RepoAnalysis> & {
12
+ __analyzerErrors?: AnalyzerError[];
13
+ };
14
+ export declare function runAnalyzers(rootDir: string, analyzers: Analyzer[]): Promise<MergedAnalysis>;
15
+ //# sourceMappingURL=analyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../../src/onboard/analyzer.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE/D,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC,CAAC;CAChE;AAKD,MAAM,MAAM,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC,GAAG;IACnD,gBAAgB,CAAC,EAAE,aAAa,EAAE,CAAC;CACpC,CAAC;AAEF,wBAAsB,YAAY,CAChC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,QAAQ,EAAE,GACpB,OAAO,CAAC,cAAc,CAAC,CA+BzB"}
@@ -0,0 +1,52 @@
1
+ export async function runAnalyzers(rootDir, analyzers) {
2
+ const results = await Promise.all(analyzers.map(async (a) => {
3
+ try {
4
+ return {
5
+ name: a.name,
6
+ value: await a.detect(rootDir),
7
+ error: null,
8
+ };
9
+ }
10
+ catch (e) {
11
+ return {
12
+ name: a.name,
13
+ value: null,
14
+ error: e instanceof Error ? e.message : String(e),
15
+ };
16
+ }
17
+ }));
18
+ const merged = {};
19
+ const errors = [];
20
+ for (const r of results) {
21
+ if (r.error !== null) {
22
+ errors.push({ name: r.name, error: r.error });
23
+ continue;
24
+ }
25
+ if (r.value === null)
26
+ continue;
27
+ mergeInto(merged, r.value);
28
+ }
29
+ if (errors.length > 0)
30
+ merged.__analyzerErrors = errors;
31
+ return merged;
32
+ }
33
+ function mergeInto(target, source) {
34
+ for (const [key, value] of Object.entries(source)) {
35
+ if (value === undefined)
36
+ continue;
37
+ if (Array.isArray(value)) {
38
+ const existing = target[key] ?? [];
39
+ target[key] = [...existing, ...value];
40
+ }
41
+ else if (typeof value === "object" &&
42
+ value !== null &&
43
+ !Array.isArray(value)) {
44
+ const existing = target[key] ?? {};
45
+ target[key] = { ...existing, ...value };
46
+ }
47
+ else {
48
+ target[key] = value;
49
+ }
50
+ }
51
+ }
52
+ //# sourceMappingURL=analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../../src/onboard/analyzer.ts"],"names":[],"mappings":"AAwBA,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,OAAe,EACf,SAAqB;IAErB,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;QACxB,IAAI,CAAC;YACH,OAAO;gBACL,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,KAAK,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC;gBAC9B,KAAK,EAAE,IAAqB;aAC7B,CAAC;QACJ,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO;gBACL,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,KAAK,EAAE,IAAI;gBACX,KAAK,EAAE,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;aAClD,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CACH,CAAC;IAEF,MAAM,MAAM,GAAmB,EAAE,CAAC;IAClC,MAAM,MAAM,GAAoB,EAAE,CAAC;IACnC,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;YACrB,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;YAC9C,SAAS;QACX,CAAC;QACD,IAAI,CAAC,CAAC,KAAK,KAAK,IAAI;YAAE,SAAS;QAC/B,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,CAAC,gBAAgB,GAAG,MAAM,CAAC;IACxD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,SAAS,CAChB,MAAsB,EACtB,MAA6B;IAE7B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAG7C,EAAE,CAAC;QACJ,IAAI,KAAK,KAAK,SAAS;YAAE,SAAS;QAClC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAI,MAAM,CAAC,GAAG,CAA2B,IAAI,EAAE,CAAC;YAC7D,MAAkC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,QAAQ,EAAE,GAAG,KAAK,CAAC,CAAC;QACrE,CAAC;aAAM,IACL,OAAO,KAAK,KAAK,QAAQ;YACzB,KAAK,KAAK,IAAI;YACd,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EACrB,CAAC;YACD,MAAM,QAAQ,GACX,MAAM,CAAC,GAAG,CAAyC,IAAI,EAAE,CAAC;YAC5D,MAAkC,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,GAAG,KAAK,EAAE,CAAC;QACvE,CAAC;aAAM,CAAC;YACL,MAAkC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACnD,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Analyzer } from "../analyzer.js";
2
+ export declare const ciAnalyzer: Analyzer;
3
+ //# sourceMappingURL=ci.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ci.d.ts","sourceRoot":"","sources":["../../../src/onboard/analyzers/ci.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAc/C,eAAO,MAAM,UAAU,EAAE,QA8CxB,CAAC"}
@@ -0,0 +1,112 @@
1
+ // packages/cli/src/onboard/analyzers/ci.ts
2
+ import { readdir, readFile } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ import { parse as parseYaml } from "yaml";
5
+ const DEPLOY_VERBS = [
6
+ { re: /\bhelm\s+(upgrade|install)\b/, target: "helm" },
7
+ { re: /\bgh\s+release\s+create\b/, target: "gh-release" },
8
+ { re: /\bgcloud\s+run\s+deploy\b/, target: "gcloud-run" },
9
+ { re: /\bgcloud\s+builds\s+submit\b/, target: "gcloud-run" },
10
+ { re: /\baws\s+ecs\s+update-service\b/, target: "ecs" },
11
+ { re: /\bvercel\s+deploy\b/, target: "vercel" },
12
+ { re: /\bflyctl\s+deploy\b/, target: "fly" },
13
+ { re: /\bkubectl\s+apply\b/, target: "kubernetes" },
14
+ ];
15
+ export const ciAnalyzer = {
16
+ name: "ci",
17
+ async detect(rootDir) {
18
+ const wfDir = join(rootDir, ".github", "workflows");
19
+ let entries;
20
+ try {
21
+ entries = (await readdir(wfDir)).filter((f) => f.endsWith(".yml") || f.endsWith(".yaml"));
22
+ }
23
+ catch {
24
+ return null;
25
+ }
26
+ if (entries.length === 0)
27
+ return null;
28
+ const workflows = [];
29
+ let deployStory = null;
30
+ for (const name of entries) {
31
+ const path = join(wfDir, name);
32
+ const raw = await readFile(path, "utf8");
33
+ let parsed;
34
+ try {
35
+ parsed = parseYaml(raw);
36
+ }
37
+ catch {
38
+ continue;
39
+ }
40
+ if (!parsed || typeof parsed !== "object")
41
+ continue;
42
+ const p = parsed;
43
+ const triggers = normalizeTriggers(p.on);
44
+ const jobs = Object.keys(p.jobs ?? {});
45
+ const matrixDimensions = collectMatrixDims(p);
46
+ workflows.push({
47
+ name: typeof p.name === "string" ? p.name : name,
48
+ path: `.github/workflows/${name}`,
49
+ triggers,
50
+ jobs,
51
+ matrixDimensions,
52
+ });
53
+ if (!deployStory) {
54
+ deployStory = findDeployCommand(p, `.github/workflows/${name}`);
55
+ }
56
+ }
57
+ return { ci: { workflows, deployStory } };
58
+ },
59
+ };
60
+ function normalizeTriggers(on) {
61
+ if (typeof on === "string")
62
+ return [on];
63
+ if (Array.isArray(on))
64
+ return on.filter((x) => typeof x === "string");
65
+ if (on && typeof on === "object")
66
+ return Object.keys(on);
67
+ return [];
68
+ }
69
+ function collectMatrixDims(parsed) {
70
+ const dims = new Set();
71
+ const jobs = parsed.jobs ?? {};
72
+ for (const job of Object.values(jobs)) {
73
+ if (!job || typeof job !== "object")
74
+ continue;
75
+ const strategy = job.strategy;
76
+ if (!strategy || typeof strategy !== "object")
77
+ continue;
78
+ const matrix = strategy.matrix;
79
+ if (!matrix || typeof matrix !== "object")
80
+ continue;
81
+ for (const k of Object.keys(matrix)) {
82
+ if (k !== "include" && k !== "exclude")
83
+ dims.add(k);
84
+ }
85
+ }
86
+ return [...dims];
87
+ }
88
+ function findDeployCommand(parsed, workflowPath) {
89
+ const jobs = parsed.jobs ?? {};
90
+ for (const job of Object.values(jobs)) {
91
+ if (!job || typeof job !== "object")
92
+ continue;
93
+ const steps = job.steps;
94
+ if (!Array.isArray(steps))
95
+ continue;
96
+ for (const step of steps) {
97
+ if (!step || typeof step !== "object")
98
+ continue;
99
+ const run = step.run;
100
+ if (typeof run !== "string")
101
+ continue;
102
+ for (const line of run.split(/\n/)) {
103
+ for (const { re, target } of DEPLOY_VERBS) {
104
+ if (re.test(line))
105
+ return { workflowPath, command: line.trim(), target };
106
+ }
107
+ }
108
+ }
109
+ }
110
+ return null;
111
+ }
112
+ //# sourceMappingURL=ci.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ci.js","sourceRoot":"","sources":["../../../src/onboard/analyzers/ci.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Analyzer } from "../analyzer.js";
2
+ export declare const docsAnalyzer: Analyzer;
3
+ //# sourceMappingURL=docs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docs.d.ts","sourceRoot":"","sources":["../../../src/onboard/analyzers/docs.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AA8F/C,eAAO,MAAM,YAAY,EAAE,QAsD1B,CAAC"}
@@ -0,0 +1,151 @@
1
+ // packages/cli/src/onboard/analyzers/docs.ts
2
+ //
3
+ // Cycle 15 Phase A — Task 8. Two concerns merged in one analyzer because both
4
+ // walk the top of the tree once:
5
+ //
6
+ // 1. Docs scan — populate docs.existing[] (README/CONTRIBUTING/CHANGELOG/
7
+ // ARCHITECTURE at root + every docs/**/*.md, cap 50), set hasClaudeMd /
8
+ // hasAgentsMd, derive agentContextSetPresent, and (per D2 lines 142–145)
9
+ // capture the structural envelope of CLAUDE.md / AGENTS.md when present —
10
+ // sizeBytes + ordered H1+H2 heading list, cap 50. Bodies are NEVER stored.
11
+ //
12
+ // 2. DF gate-presence check — populate dfPresence.{hooks, configJson,
13
+ // prWorkflow, cliPin}. cliPin parses the @momentiq/dark-factory-cli
14
+ // version from the ROOT package.json (dependencies first, then
15
+ // devDependencies), verbatim, or null if absent.
16
+ import { readdir, readFile, stat } from "node:fs/promises";
17
+ import { join, relative, sep } from "node:path";
18
+ const ROOT_DOC_FILES = [
19
+ "README.md",
20
+ "CONTRIBUTING.md",
21
+ "CHANGELOG.md",
22
+ "ARCHITECTURE.md",
23
+ ];
24
+ const MAX_DOCS = 50;
25
+ const MAX_HEADINGS = 50;
26
+ async function isFile(p) {
27
+ try {
28
+ return (await stat(p)).isFile();
29
+ }
30
+ catch {
31
+ return false;
32
+ }
33
+ }
34
+ async function isDir(p) {
35
+ try {
36
+ return (await stat(p)).isDirectory();
37
+ }
38
+ catch {
39
+ return false;
40
+ }
41
+ }
42
+ // Recursive walk of docs/ collecting *.md paths (forward-slash-relative to
43
+ // rootDir). The output array is shared with the root-doc scan, so we stop as
44
+ // soon as it hits MAX_DOCS — the cap is on the COMBINED list.
45
+ async function walkDocsDir(docsRoot, rootDir, out) {
46
+ if (out.length >= MAX_DOCS)
47
+ return;
48
+ let entries;
49
+ try {
50
+ entries = await readdir(docsRoot, { withFileTypes: true });
51
+ }
52
+ catch {
53
+ return;
54
+ }
55
+ // Stable ordering: filesystem readdir is not guaranteed sorted on all
56
+ // platforms; sort by name so the analysis envelope is deterministic.
57
+ entries.sort((a, b) => a.name.localeCompare(b.name));
58
+ for (const entry of entries) {
59
+ if (out.length >= MAX_DOCS)
60
+ return;
61
+ const p = join(docsRoot, entry.name);
62
+ if (entry.isDirectory()) {
63
+ await walkDocsDir(p, rootDir, out);
64
+ }
65
+ else if (entry.isFile() && entry.name.endsWith(".md")) {
66
+ out.push(relative(rootDir, p).split(sep).join("/"));
67
+ }
68
+ }
69
+ }
70
+ // Extract H1+H2 headings from a markdown body. Tracks fenced code block state
71
+ // so a `# foo` line inside a ```-fence is NOT counted as a heading. Strips
72
+ // trailing whitespace from each captured heading. Caps the list at
73
+ // MAX_HEADINGS (silent truncation — the test pins this behavior).
74
+ function extractHeadings(body) {
75
+ const sizeBytes = Buffer.byteLength(body, "utf8");
76
+ const headings = [];
77
+ let inFence = false;
78
+ for (const line of body.split(/\r?\n/)) {
79
+ const trimmed = line.trimEnd();
80
+ // Treat any ```-prefix line (optionally indented) as a fence toggle.
81
+ if (/^\s*```/.test(trimmed)) {
82
+ inFence = !inFence;
83
+ continue;
84
+ }
85
+ if (inFence)
86
+ continue;
87
+ const m = trimmed.match(/^#{1,2}\s+(.+)$/);
88
+ if (m && m[1] !== undefined) {
89
+ headings.push(m[1].trimEnd());
90
+ if (headings.length >= MAX_HEADINGS)
91
+ break;
92
+ }
93
+ }
94
+ return { sizeBytes, headings };
95
+ }
96
+ async function readAgentFile(p) {
97
+ try {
98
+ const body = await readFile(p, "utf8");
99
+ return extractHeadings(body);
100
+ }
101
+ catch {
102
+ return null;
103
+ }
104
+ }
105
+ export const docsAnalyzer = {
106
+ name: "docs",
107
+ async detect(rootDir) {
108
+ const existing = [];
109
+ for (const name of ROOT_DOC_FILES) {
110
+ if (existing.length >= MAX_DOCS)
111
+ break;
112
+ if (await isFile(join(rootDir, name)))
113
+ existing.push(name);
114
+ }
115
+ await walkDocsDir(join(rootDir, "docs"), rootDir, existing);
116
+ const claudeMd = await readAgentFile(join(rootDir, "CLAUDE.md"));
117
+ const agentsMd = await readAgentFile(join(rootDir, "AGENTS.md"));
118
+ const hasClaudeMd = claudeMd !== null;
119
+ const hasAgentsMd = agentsMd !== null;
120
+ const agentContextSetPresent = hasClaudeMd &&
121
+ hasAgentsMd &&
122
+ existing.some((p) => p.startsWith("docs/"));
123
+ const hooks = await isDir(join(rootDir, ".husky"));
124
+ const configJson = await isFile(join(rootDir, ".agent-review", "config.json"));
125
+ const prWorkflow = await isFile(join(rootDir, ".github", "workflows", "dark-factory-pr.yml"));
126
+ let cliPin = null;
127
+ try {
128
+ const pkgRaw = await readFile(join(rootDir, "package.json"), "utf8");
129
+ const pkg = JSON.parse(pkgRaw);
130
+ cliPin =
131
+ pkg?.dependencies?.["@momentiq/dark-factory-cli"] ??
132
+ pkg?.devDependencies?.["@momentiq/dark-factory-cli"] ??
133
+ null;
134
+ }
135
+ catch {
136
+ cliPin = null;
137
+ }
138
+ return {
139
+ docs: {
140
+ existing: existing.slice(0, MAX_DOCS),
141
+ hasClaudeMd,
142
+ hasAgentsMd,
143
+ agentContextSetPresent,
144
+ claudeMd,
145
+ agentsMd,
146
+ },
147
+ dfPresence: { hooks, configJson, prWorkflow, cliPin },
148
+ };
149
+ },
150
+ };
151
+ //# sourceMappingURL=docs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docs.js","sourceRoot":"","sources":["../../../src/onboard/analyzers/docs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Analyzer } from "../analyzer.js";
2
+ export declare const gitAnalyzer: Analyzer;
3
+ //# sourceMappingURL=git.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../../src/onboard/analyzers/git.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAiC/C,eAAO,MAAM,WAAW,EAAE,QAqDzB,CAAC"}
@@ -0,0 +1,87 @@
1
+ // packages/cli/src/onboard/analyzers/git.ts
2
+ //
3
+ // Cycle 15 Phase A — Task 7. Populates:
4
+ // - canonicalName (owner/repo from origin remote, HTTPS or SSH)
5
+ // - git.defaultBranch (origin/HEAD symref, falling back to local HEAD)
6
+ // - git.recentCommitConventions.{conventional,cycleReferenced}
7
+ // (derived from up to the last 200 commit subjects)
8
+ //
9
+ // Returns null when the directory isn't a git repo, when git commands fail,
10
+ // or when the repo has no commits yet (zero-subject sample = no signal).
11
+ import { execFile } from "node:child_process";
12
+ import { promisify } from "node:util";
13
+ const ex = promisify(execFile);
14
+ async function gitOut(cwd, args) {
15
+ try {
16
+ const { stdout } = await ex("git", args, {
17
+ cwd,
18
+ maxBuffer: 10 * 1024 * 1024,
19
+ });
20
+ return stdout;
21
+ }
22
+ catch {
23
+ return null;
24
+ }
25
+ }
26
+ // HTTPS form: https://host/owner/repo[.git]
27
+ // SSH form: user@host:owner/repo[.git]
28
+ // Host-agnostic by design (works for github.com, gitlab.com, self-hosted, …).
29
+ function parseCanonicalName(remoteUrl) {
30
+ const https = remoteUrl.match(/^https?:\/\/[^/]+\/([^/]+)\/([^/]+?)(?:\.git)?$/);
31
+ if (https)
32
+ return `${https[1]}/${https[2]}`;
33
+ const ssh = remoteUrl.match(/^[^@]+@[^:]+:([^/]+)\/([^/]+?)(?:\.git)?$/);
34
+ if (ssh)
35
+ return `${ssh[1]}/${ssh[2]}`;
36
+ return "";
37
+ }
38
+ const CONVENTIONAL_RE = /^(feat|fix|docs|chore|refactor|test|perf|build|ci)(\([^)]+\))?(!)?:\s/;
39
+ const CYCLE_RE = /[Cc]ycle \d+|closes #\d+/;
40
+ export const gitAnalyzer = {
41
+ name: "git",
42
+ async detect(rootDir) {
43
+ // Cheapest probe: `git rev-parse --git-dir` confirms it's a git repo.
44
+ const gitDir = await gitOut(rootDir, ["rev-parse", "--git-dir"]);
45
+ if (gitDir === null)
46
+ return null;
47
+ // Origin remote → canonicalName. Missing remote is fine (empty string).
48
+ const remote = (await gitOut(rootDir, ["remote", "get-url", "origin"]))?.trim() ?? "";
49
+ const canonicalName = remote ? parseCanonicalName(remote) : "";
50
+ // Default branch: prefer origin/HEAD symref, fall back to local HEAD,
51
+ // final fallback "main" so the schema always has a non-empty string.
52
+ let defaultBranch = "main";
53
+ const symRef = (await gitOut(rootDir, [
54
+ "symbolic-ref",
55
+ "--quiet",
56
+ "refs/remotes/origin/HEAD",
57
+ ]))?.trim();
58
+ if (symRef && symRef.startsWith("refs/remotes/origin/")) {
59
+ defaultBranch = symRef.slice("refs/remotes/origin/".length);
60
+ }
61
+ else {
62
+ const head = (await gitOut(rootDir, ["rev-parse", "--abbrev-ref", "HEAD"]))?.trim();
63
+ if (head && head !== "HEAD")
64
+ defaultBranch = head;
65
+ }
66
+ // Sample the last 200 subjects. A fresh repo with zero commits returns
67
+ // null — we cannot make a conventional/cycle call without any signal.
68
+ const subjectsBlob = (await gitOut(rootDir, ["log", "--pretty=%s", "-200"])) ?? "";
69
+ const subjects = subjectsBlob
70
+ .split(/\r?\n/)
71
+ .filter((s) => s.length > 0);
72
+ if (subjects.length === 0)
73
+ return null;
74
+ const convCount = subjects.filter((s) => CONVENTIONAL_RE.test(s)).length;
75
+ const cycleCount = subjects.filter((s) => CYCLE_RE.test(s)).length;
76
+ const conventional = convCount / subjects.length >= 0.3;
77
+ const cycleReferenced = cycleCount / subjects.length >= 0.2;
78
+ return {
79
+ canonicalName,
80
+ git: {
81
+ recentCommitConventions: { conventional, cycleReferenced },
82
+ defaultBranch,
83
+ },
84
+ };
85
+ },
86
+ };
87
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../../src/onboard/analyzers/git.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Analyzer } from "../analyzer.js";
2
+ export declare const lockfileAnalyzer: Analyzer;
3
+ //# sourceMappingURL=lockfile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lockfile.d.ts","sourceRoot":"","sources":["../../../src/onboard/analyzers/lockfile.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AA2P/C,eAAO,MAAM,gBAAgB,EAAE,QAyB9B,CAAC"}