@momentiq/dark-factory-cli 2.0.0 → 2.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 (142) hide show
  1. package/dist/adapters/static-schema-lint.js +1 -1
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +18 -1
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/onboard.d.ts +69 -0
  6. package/dist/commands/onboard.d.ts.map +1 -0
  7. package/dist/commands/onboard.js +323 -0
  8. package/dist/commands/onboard.js.map +1 -0
  9. package/dist/cycle-doc-validator/validate_cycle_doc.py +131 -60
  10. package/dist/doctor.d.ts.map +1 -1
  11. package/dist/doctor.js +20 -0
  12. package/dist/doctor.js.map +1 -1
  13. package/dist/mcp/server.d.ts.map +1 -1
  14. package/dist/mcp/server.js +2 -0
  15. package/dist/mcp/server.js.map +1 -1
  16. package/dist/mcp/tools/onboard.d.ts +6 -0
  17. package/dist/mcp/tools/onboard.d.ts.map +1 -0
  18. package/dist/mcp/tools/onboard.js +115 -0
  19. package/dist/mcp/tools/onboard.js.map +1 -0
  20. package/dist/onboard/analyze.d.ts +7 -0
  21. package/dist/onboard/analyze.d.ts.map +1 -0
  22. package/dist/onboard/analyze.js +86 -0
  23. package/dist/onboard/analyze.js.map +1 -0
  24. package/dist/onboard/analyzer.d.ts +15 -0
  25. package/dist/onboard/analyzer.d.ts.map +1 -0
  26. package/dist/onboard/analyzer.js +52 -0
  27. package/dist/onboard/analyzer.js.map +1 -0
  28. package/dist/onboard/analyzers/ci.d.ts +3 -0
  29. package/dist/onboard/analyzers/ci.d.ts.map +1 -0
  30. package/dist/onboard/analyzers/ci.js +112 -0
  31. package/dist/onboard/analyzers/ci.js.map +1 -0
  32. package/dist/onboard/analyzers/docs.d.ts +3 -0
  33. package/dist/onboard/analyzers/docs.d.ts.map +1 -0
  34. package/dist/onboard/analyzers/docs.js +151 -0
  35. package/dist/onboard/analyzers/docs.js.map +1 -0
  36. package/dist/onboard/analyzers/git.d.ts +3 -0
  37. package/dist/onboard/analyzers/git.d.ts.map +1 -0
  38. package/dist/onboard/analyzers/git.js +87 -0
  39. package/dist/onboard/analyzers/git.js.map +1 -0
  40. package/dist/onboard/analyzers/lockfile.d.ts +3 -0
  41. package/dist/onboard/analyzers/lockfile.d.ts.map +1 -0
  42. package/dist/onboard/analyzers/lockfile.js +285 -0
  43. package/dist/onboard/analyzers/lockfile.js.map +1 -0
  44. package/dist/onboard/analyzers/manifest.d.ts +3 -0
  45. package/dist/onboard/analyzers/manifest.d.ts.map +1 -0
  46. package/dist/onboard/analyzers/manifest.js +228 -0
  47. package/dist/onboard/analyzers/manifest.js.map +1 -0
  48. package/dist/onboard/analyzers/tree.d.ts +3 -0
  49. package/dist/onboard/analyzers/tree.d.ts.map +1 -0
  50. package/dist/onboard/analyzers/tree.js +196 -0
  51. package/dist/onboard/analyzers/tree.js.map +1 -0
  52. package/dist/onboard/apply-plan.d.ts +29 -0
  53. package/dist/onboard/apply-plan.d.ts.map +1 -0
  54. package/dist/onboard/apply-plan.js +80 -0
  55. package/dist/onboard/apply-plan.js.map +1 -0
  56. package/dist/onboard/auto-profile.d.ts +3 -0
  57. package/dist/onboard/auto-profile.d.ts.map +1 -0
  58. package/dist/onboard/auto-profile.js +20 -0
  59. package/dist/onboard/auto-profile.js.map +1 -0
  60. package/dist/onboard/fixtures/replay-git-history.d.ts +20 -0
  61. package/dist/onboard/fixtures/replay-git-history.d.ts.map +1 -0
  62. package/dist/onboard/fixtures/replay-git-history.js +91 -0
  63. package/dist/onboard/fixtures/replay-git-history.js.map +1 -0
  64. package/dist/onboard/generate-plan.d.ts +18 -0
  65. package/dist/onboard/generate-plan.d.ts.map +1 -0
  66. package/dist/onboard/generate-plan.js +68 -0
  67. package/dist/onboard/generate-plan.js.map +1 -0
  68. package/dist/onboard/llm-client.d.ts +45 -0
  69. package/dist/onboard/llm-client.d.ts.map +1 -0
  70. package/dist/onboard/llm-client.js +84 -0
  71. package/dist/onboard/llm-client.js.map +1 -0
  72. package/dist/onboard/prompts/scaffold.md +93 -0
  73. package/dist/onboard/prompts.d.ts +13 -0
  74. package/dist/onboard/prompts.d.ts.map +1 -0
  75. package/dist/onboard/prompts.js +54 -0
  76. package/dist/onboard/prompts.js.map +1 -0
  77. package/dist/onboard/scaffold-schema.d.ts +194 -0
  78. package/dist/onboard/scaffold-schema.d.ts.map +1 -0
  79. package/dist/onboard/scaffold-schema.js +73 -0
  80. package/dist/onboard/scaffold-schema.js.map +1 -0
  81. package/dist/onboard/schema.d.ts +545 -0
  82. package/dist/onboard/schema.d.ts.map +1 -0
  83. package/dist/onboard/schema.js +148 -0
  84. package/dist/onboard/schema.js.map +1 -0
  85. package/dist/onboard/seeders/adr.d.ts +3 -0
  86. package/dist/onboard/seeders/adr.d.ts.map +1 -0
  87. package/dist/onboard/seeders/adr.js +212 -0
  88. package/dist/onboard/seeders/adr.js.map +1 -0
  89. package/dist/onboard/seeders/agent-review-config/cloud.canonical.json +22 -0
  90. package/dist/onboard/seeders/agent-review-config/local.canonical.json +21 -0
  91. package/dist/onboard/seeders/agent-review-config.d.ts +3 -0
  92. package/dist/onboard/seeders/agent-review-config.d.ts.map +1 -0
  93. package/dist/onboard/seeders/agent-review-config.js +38 -0
  94. package/dist/onboard/seeders/agent-review-config.js.map +1 -0
  95. package/dist/onboard/seeders/cycle1-bootstrap.d.ts +3 -0
  96. package/dist/onboard/seeders/cycle1-bootstrap.d.ts.map +1 -0
  97. package/dist/onboard/seeders/cycle1-bootstrap.js +76 -0
  98. package/dist/onboard/seeders/cycle1-bootstrap.js.map +1 -0
  99. package/dist/onboard/seeders/index.d.ts +47 -0
  100. package/dist/onboard/seeders/index.d.ts.map +1 -0
  101. package/dist/onboard/seeders/index.js +37 -0
  102. package/dist/onboard/seeders/index.js.map +1 -0
  103. package/dist/onboard/seeders/runbook.d.ts +13 -0
  104. package/dist/onboard/seeders/runbook.d.ts.map +1 -0
  105. package/dist/onboard/seeders/runbook.js +85 -0
  106. package/dist/onboard/seeders/runbook.js.map +1 -0
  107. package/dist/onboard/seeders/templates/adr.md.tmpl +26 -0
  108. package/dist/onboard/seeders/templates/cycle1-bootstrap.md.tmpl +64 -0
  109. package/dist/onboard/seeders/templates/runbook.md.tmpl +26 -0
  110. package/dist/onboard/template-loader.d.ts +20 -0
  111. package/dist/onboard/template-loader.d.ts.map +1 -0
  112. package/dist/onboard/template-loader.js +143 -0
  113. package/dist/onboard/template-loader.js.map +1 -0
  114. package/dist/onboard/template-ref.d.ts +15 -0
  115. package/dist/onboard/template-ref.d.ts.map +1 -0
  116. package/dist/onboard/template-ref.js +45 -0
  117. package/dist/onboard/template-ref.js.map +1 -0
  118. package/dist/onboard/validate.d.ts +19 -0
  119. package/dist/onboard/validate.d.ts.map +1 -0
  120. package/dist/onboard/validate.js +127 -0
  121. package/dist/onboard/validate.js.map +1 -0
  122. package/dist/onboard/writers/dry-run-renderer.d.ts +6 -0
  123. package/dist/onboard/writers/dry-run-renderer.d.ts.map +1 -0
  124. package/dist/onboard/writers/dry-run-renderer.js +88 -0
  125. package/dist/onboard/writers/dry-run-renderer.js.map +1 -0
  126. package/dist/onboard/writers/emit.d.ts +6 -0
  127. package/dist/onboard/writers/emit.d.ts.map +1 -0
  128. package/dist/onboard/writers/emit.js +29 -0
  129. package/dist/onboard/writers/emit.js.map +1 -0
  130. package/dist/onboard/writers/merge.d.ts +16 -0
  131. package/dist/onboard/writers/merge.d.ts.map +1 -0
  132. package/dist/onboard/writers/merge.js +142 -0
  133. package/dist/onboard/writers/merge.js.map +1 -0
  134. package/dist/onboard/writers/pr-writer.d.ts +44 -0
  135. package/dist/onboard/writers/pr-writer.d.ts.map +1 -0
  136. package/dist/onboard/writers/pr-writer.js +104 -0
  137. package/dist/onboard/writers/pr-writer.js.map +1 -0
  138. package/dist/onboard/writers/skip.d.ts +9 -0
  139. package/dist/onboard/writers/skip.d.ts.map +1 -0
  140. package/dist/onboard/writers/skip.js +9 -0
  141. package/dist/onboard/writers/skip.js.map +1 -0
  142. package/package.json +8 -1
@@ -0,0 +1,228 @@
1
+ // packages/cli/src/onboard/analyzers/manifest.ts
2
+ //
3
+ // Manifest analyzer — cycle 15 Phase A, Task 3.
4
+ //
5
+ // Detects every stack present in a repo from primary manifests (package.json,
6
+ // pyproject.toml, go.mod, Cargo.toml, Gemfile, mix.exs, pom.xml,
7
+ // build.gradle.kts), plus the asdf/mise multi-runtime `.tool-versions` file,
8
+ // plus a Dockerfile fallback signal. Populates `RepoAnalysis.stacks[]`.
9
+ import { readFile } from "node:fs/promises";
10
+ import { join } from "node:path";
11
+ import { parse as parseToml } from "@iarna/toml";
12
+ async function readIfExists(p) {
13
+ try {
14
+ return await readFile(p, "utf8");
15
+ }
16
+ catch {
17
+ return null;
18
+ }
19
+ }
20
+ async function detectNode(root) {
21
+ const pkg = await readIfExists(join(root, "package.json"));
22
+ if (!pkg)
23
+ return null;
24
+ let pin = null;
25
+ try {
26
+ const p = JSON.parse(pkg);
27
+ pin = p.engines?.node ?? p.volta?.node ?? null;
28
+ }
29
+ catch {
30
+ /* malformed package.json — pin stays null */
31
+ }
32
+ if (!pin) {
33
+ const nvmrc = await readIfExists(join(root, ".nvmrc"));
34
+ if (nvmrc)
35
+ pin = nvmrc.trim();
36
+ }
37
+ return { language: "typescript", versionPin: pin, manifestPath: "package.json" };
38
+ }
39
+ async function detectPython(root) {
40
+ const py = await readIfExists(join(root, "pyproject.toml"));
41
+ if (!py)
42
+ return null;
43
+ let pin = null;
44
+ try {
45
+ const parsed = parseToml(py);
46
+ pin =
47
+ parsed.tool?.poetry?.dependencies?.python ??
48
+ parsed.project?.["requires-python"] ??
49
+ null;
50
+ }
51
+ catch {
52
+ /* malformed pyproject.toml — pin stays null */
53
+ }
54
+ if (!pin) {
55
+ const pv = await readIfExists(join(root, ".python-version"));
56
+ if (pv)
57
+ pin = pv.trim() || null;
58
+ }
59
+ return { language: "python", versionPin: pin, manifestPath: "pyproject.toml" };
60
+ }
61
+ async function detectGo(root) {
62
+ const body = await readIfExists(join(root, "go.mod"));
63
+ if (!body)
64
+ return null;
65
+ const m = body.match(/^go\s+(\S+)/m);
66
+ return {
67
+ language: "go",
68
+ versionPin: m?.[1] ?? null,
69
+ manifestPath: "go.mod",
70
+ };
71
+ }
72
+ async function detectRust(root) {
73
+ const cargo = await readIfExists(join(root, "Cargo.toml"));
74
+ if (!cargo)
75
+ return null;
76
+ let pin = null;
77
+ try {
78
+ const parsed = parseToml(cargo);
79
+ pin = parsed.package?.["rust-version"] ?? null;
80
+ }
81
+ catch {
82
+ /* malformed Cargo.toml — pin stays null */
83
+ }
84
+ if (!pin) {
85
+ const tc = await readIfExists(join(root, "rust-toolchain.toml"));
86
+ if (tc) {
87
+ try {
88
+ const parsed = parseToml(tc);
89
+ pin = parsed.toolchain?.channel ?? null;
90
+ }
91
+ catch {
92
+ /* malformed rust-toolchain.toml — pin stays null */
93
+ }
94
+ }
95
+ }
96
+ return { language: "rust", versionPin: pin, manifestPath: "Cargo.toml" };
97
+ }
98
+ async function detectRuby(root) {
99
+ const body = await readIfExists(join(root, "Gemfile"));
100
+ if (!body)
101
+ return null;
102
+ const m = body.match(/^ruby\s+['"]([^'"]+)['"]/m);
103
+ let pin = m?.[1] ?? null;
104
+ if (!pin) {
105
+ const rv = await readIfExists(join(root, ".ruby-version"));
106
+ if (rv)
107
+ pin = rv.trim() || null;
108
+ }
109
+ return { language: "ruby", versionPin: pin, manifestPath: "Gemfile" };
110
+ }
111
+ async function detectElixir(root) {
112
+ const body = await readIfExists(join(root, "mix.exs"));
113
+ if (!body)
114
+ return null;
115
+ const m = body.match(/elixir:\s*"([^"]+)"/);
116
+ return {
117
+ language: "elixir",
118
+ versionPin: m?.[1] ?? null,
119
+ manifestPath: "mix.exs",
120
+ };
121
+ }
122
+ async function detectJava(root) {
123
+ const body = await readIfExists(join(root, "pom.xml"));
124
+ if (!body)
125
+ return null;
126
+ const compiler = body.match(/<maven\.compiler\.source>([^<]+)<\/maven\.compiler\.source>/);
127
+ const javaVer = body.match(/<java\.version>([^<]+)<\/java\.version>/);
128
+ const pin = compiler?.[1] ?? javaVer?.[1] ?? null;
129
+ return { language: "java", versionPin: pin, manifestPath: "pom.xml" };
130
+ }
131
+ async function detectKotlin(root) {
132
+ const body = await readIfExists(join(root, "build.gradle.kts"));
133
+ if (!body)
134
+ return null;
135
+ const jvm = body.match(/jvmTarget\s*=\s*"([^"]+)"/);
136
+ let pin = jvm?.[1] ?? null;
137
+ if (!pin) {
138
+ const jv = body.match(/JavaVersion\.VERSION_(\d+)/);
139
+ if (jv)
140
+ pin = jv[1] ?? null;
141
+ }
142
+ return {
143
+ language: "kotlin",
144
+ versionPin: pin,
145
+ manifestPath: "build.gradle.kts",
146
+ };
147
+ }
148
+ async function detectDocker(root) {
149
+ const body = await readIfExists(join(root, "Dockerfile"));
150
+ if (!body)
151
+ return null;
152
+ const m = body.match(/^FROM\s+(\S+)/m);
153
+ return {
154
+ language: "other",
155
+ versionPin: m?.[1] ?? null,
156
+ manifestPath: "Dockerfile",
157
+ };
158
+ }
159
+ const RUNTIME_TO_LANG = {
160
+ nodejs: "typescript",
161
+ node: "typescript",
162
+ python: "python",
163
+ golang: "go",
164
+ go: "go",
165
+ ruby: "ruby",
166
+ rust: "rust",
167
+ elixir: "elixir",
168
+ java: "java",
169
+ kotlin: "kotlin",
170
+ };
171
+ async function detectToolVersions(root) {
172
+ const body = await readIfExists(join(root, ".tool-versions"));
173
+ if (!body)
174
+ return [];
175
+ const out = [];
176
+ for (const raw of body.split(/\r?\n/)) {
177
+ const line = raw.split("#")[0]?.trim();
178
+ if (!line)
179
+ continue;
180
+ const [rt, ver] = line.split(/\s+/);
181
+ if (!rt || !ver)
182
+ continue;
183
+ const lang = RUNTIME_TO_LANG[rt.toLowerCase()];
184
+ if (!lang)
185
+ continue;
186
+ out.push({ language: lang, versionPin: ver, manifestPath: ".tool-versions" });
187
+ }
188
+ return out;
189
+ }
190
+ // Merge a primary-manifest stack list with .tool-versions entries.
191
+ // Rule (see plan's "Supported manifests" table): .tool-versions pin wins for
192
+ // any language that also has a primary manifest, but the primary manifest's
193
+ // path is preserved as `manifestPath`. Languages only in .tool-versions are
194
+ // added with manifestPath: ".tool-versions". De-dupe by language.
195
+ function mergeStacks(primary, toolVersions) {
196
+ const byLang = new Map();
197
+ for (const s of primary)
198
+ byLang.set(s.language, s);
199
+ for (const tv of toolVersions) {
200
+ const existing = byLang.get(tv.language);
201
+ byLang.set(tv.language, existing ? { ...existing, versionPin: tv.versionPin } : tv);
202
+ }
203
+ return [...byLang.values()];
204
+ }
205
+ export const manifestAnalyzer = {
206
+ name: "manifest",
207
+ async detect(rootDir) {
208
+ const detectors = [
209
+ detectNode,
210
+ detectPython,
211
+ detectGo,
212
+ detectRust,
213
+ detectRuby,
214
+ detectElixir,
215
+ detectJava,
216
+ detectKotlin,
217
+ detectDocker,
218
+ ];
219
+ const primary = (await Promise.all(detectors.map((d) => d(rootDir))))
220
+ .filter((s) => s !== null);
221
+ const toolVersions = await detectToolVersions(rootDir);
222
+ const stacks = mergeStacks(primary, toolVersions);
223
+ if (stacks.length === 0)
224
+ return null;
225
+ return { stacks };
226
+ },
227
+ };
228
+ //# sourceMappingURL=manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../../src/onboard/analyzers/manifest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Analyzer } from "../analyzer.js";
2
+ export declare const treeAnalyzer: Analyzer;
3
+ //# sourceMappingURL=tree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree.d.ts","sourceRoot":"","sources":["../../../src/onboard/analyzers/tree.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAgK/C,eAAO,MAAM,YAAY,EAAE,QA+D1B,CAAC"}
@@ -0,0 +1,196 @@
1
+ import { readdir } from "node:fs/promises";
2
+ import { extname, join } from "node:path";
3
+ const SKIP_DIR_NAMES = new Set([
4
+ "node_modules",
5
+ "dist",
6
+ "build",
7
+ "target",
8
+ ".next",
9
+ ".venv",
10
+ "__pycache__",
11
+ ".gradle",
12
+ ]);
13
+ const DIR_CATEGORY = {
14
+ services: "services",
15
+ apps: "services",
16
+ packages: "packages",
17
+ src: "src",
18
+ lib: "src",
19
+ tests: "tests",
20
+ test: "tests",
21
+ __tests__: "tests",
22
+ docs: "docs",
23
+ documentation: "docs",
24
+ infra: "infra",
25
+ terraform: "infra",
26
+ deploy: "infra",
27
+ scripts: "scripts",
28
+ bin: "scripts",
29
+ tools: "scripts",
30
+ };
31
+ const EXT_LANG = {
32
+ ".ts": "typescript",
33
+ ".tsx": "typescript",
34
+ ".js": "javascript",
35
+ ".jsx": "javascript",
36
+ ".mjs": "javascript",
37
+ ".cjs": "javascript",
38
+ ".py": "python",
39
+ ".go": "go",
40
+ ".rs": "rust",
41
+ ".rb": "ruby",
42
+ ".ex": "elixir",
43
+ ".exs": "elixir",
44
+ ".java": "java",
45
+ ".kt": "kotlin",
46
+ ".kts": "kotlin",
47
+ ".cs": "csharp",
48
+ ".swift": "swift",
49
+ ".md": "markdown",
50
+ ".yaml": "yaml",
51
+ ".yml": "yaml",
52
+ ".json": "json",
53
+ };
54
+ const TEST_DIR_NAMES = new Set(["tests", "test", "__tests__", "spec"]);
55
+ const MAX_DEPTH = 4;
56
+ const MAX_FILES = 50_000;
57
+ const MAX_TOP_LEVEL_DIRS = 30;
58
+ const MAX_TEST_DIRS = 20;
59
+ const MAX_SERVICES = 30;
60
+ class FileCapExceededError extends Error {
61
+ constructor() {
62
+ super(`tree analyzer exceeded ${MAX_FILES.toLocaleString()} file cap`);
63
+ this.name = "FileCapExceededError";
64
+ }
65
+ }
66
+ function shouldSkipEntry(name) {
67
+ // Skip every hidden entry (`.git`, `.github`, `.vscode`, dotfiles…) and
68
+ // every well-known build-artifact directory.
69
+ if (name.startsWith("."))
70
+ return true;
71
+ if (SKIP_DIR_NAMES.has(name))
72
+ return true;
73
+ return false;
74
+ }
75
+ async function walk(absPath, relPath, depth, topLevelName, state) {
76
+ if (depth > MAX_DEPTH)
77
+ return;
78
+ let entries;
79
+ try {
80
+ entries = await readdir(absPath, { withFileTypes: true });
81
+ }
82
+ catch {
83
+ // Permission denied or transient — treat as empty so the analyzer
84
+ // doesn't bomb the whole onboarding pass over one unreadable subtree.
85
+ return;
86
+ }
87
+ for (const entry of entries) {
88
+ if (shouldSkipEntry(entry.name))
89
+ continue;
90
+ const childRel = relPath === "" ? entry.name : `${relPath}/${entry.name}`;
91
+ const childAbs = join(absPath, entry.name);
92
+ if (entry.isDirectory()) {
93
+ // testDirs: any directory whose basename matches tests/test/__tests__/spec
94
+ // at depth ≤ 3 (the directory itself sits at depth+1 from root).
95
+ const dirDepth = depth + 1;
96
+ if (dirDepth <= 3 &&
97
+ TEST_DIR_NAMES.has(entry.name) &&
98
+ state.testDirs.length < MAX_TEST_DIRS &&
99
+ !state.testDirs.includes(childRel)) {
100
+ state.testDirs.push(childRel);
101
+ }
102
+ await walk(childAbs, childRel, depth + 1, topLevelName ?? entry.name, state);
103
+ }
104
+ else if (entry.isFile()) {
105
+ state.fileCount += 1;
106
+ if (state.fileCount > MAX_FILES)
107
+ throw new FileCapExceededError();
108
+ const ext = extname(entry.name).toLowerCase();
109
+ const bucket = EXT_LANG[ext] ?? "other";
110
+ state.languageBreakdown[bucket] =
111
+ (state.languageBreakdown[bucket] ?? 0) + 1;
112
+ if (topLevelName !== null) {
113
+ state.topLevelFileCounts.set(topLevelName, (state.topLevelFileCounts.get(topLevelName) ?? 0) + 1);
114
+ }
115
+ }
116
+ // Symlinks and other types are ignored — we only follow concrete files
117
+ // and directories, which matches the manifest analyzer's posture.
118
+ }
119
+ }
120
+ function classify(name) {
121
+ return DIR_CATEGORY[name] ?? "other";
122
+ }
123
+ async function listImmediateDirs(absPath) {
124
+ try {
125
+ const entries = await readdir(absPath, { withFileTypes: true });
126
+ return entries
127
+ .filter((e) => e.isDirectory() && !shouldSkipEntry(e.name))
128
+ .map((e) => e.name);
129
+ }
130
+ catch {
131
+ return [];
132
+ }
133
+ }
134
+ export const treeAnalyzer = {
135
+ name: "tree",
136
+ async detect(rootDir) {
137
+ const state = {
138
+ fileCount: 0,
139
+ languageBreakdown: {},
140
+ testDirs: [],
141
+ topLevelFileCounts: new Map(),
142
+ };
143
+ // Enumerate top-level entries first so we can populate `topLevelDirs`
144
+ // independent of how many files each subtree contains.
145
+ let rootEntries;
146
+ try {
147
+ rootEntries = await readdir(rootDir, { withFileTypes: true });
148
+ }
149
+ catch {
150
+ rootEntries = [];
151
+ }
152
+ const topLevelDirNames = [];
153
+ for (const entry of rootEntries) {
154
+ if (entry.isDirectory() && !shouldSkipEntry(entry.name)) {
155
+ topLevelDirNames.push(entry.name);
156
+ }
157
+ }
158
+ await walk(rootDir, "", 0, null, state);
159
+ const topLevelDirs = topLevelDirNames
160
+ .slice(0, MAX_TOP_LEVEL_DIRS)
161
+ .map((name) => ({
162
+ name,
163
+ category: classify(name),
164
+ fileCount: state.topLevelFileCounts.get(name) ?? 0,
165
+ }));
166
+ // Services discovery: immediate children of every top-level dir of
167
+ // category `services` (literally `services/` or `apps/`).
168
+ const services = [];
169
+ for (const top of topLevelDirNames) {
170
+ if (classify(top) !== "services")
171
+ continue;
172
+ const children = await listImmediateDirs(join(rootDir, top));
173
+ for (const child of children) {
174
+ if (services.length >= MAX_SERVICES)
175
+ break;
176
+ services.push({
177
+ name: child,
178
+ path: `${top}/${child}`,
179
+ stack: null,
180
+ });
181
+ }
182
+ if (services.length >= MAX_SERVICES)
183
+ break;
184
+ }
185
+ return {
186
+ tree: {
187
+ topLevelDirs,
188
+ languageBreakdown: state.languageBreakdown,
189
+ testDirs: state.testDirs.slice(0, MAX_TEST_DIRS),
190
+ fileCount: state.fileCount,
191
+ },
192
+ services,
193
+ };
194
+ },
195
+ };
196
+ //# sourceMappingURL=tree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree.js","sourceRoot":"","sources":["../../../src/onboard/analyzers/tree.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAI1C,MAAM,cAAc,GAAG,IAAI,GAAG,CAAS;IACrC,cAAc;IACd,MAAM;IACN,OAAO;IACP,QAAQ;IACR,OAAO;IACP,OAAO;IACP,aAAa;IACb,SAAS;CACV,CAAC,CAAC;AAEH,MAAM,YAAY,GAA4C;IAC5D,QAAQ,EAAE,UAAU;IACpB,IAAI,EAAE,UAAU;IAChB,QAAQ,EAAE,UAAU;IACpB,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,KAAK,EAAE,OAAO;IACd,IAAI,EAAE,OAAO;IACb,SAAS,EAAE,OAAO;IAClB,IAAI,EAAE,MAAM;IACZ,aAAa,EAAE,MAAM;IACrB,KAAK,EAAE,OAAO;IACd,SAAS,EAAE,OAAO;IAClB,MAAM,EAAE,OAAO;IACf,OAAO,EAAE,SAAS;IAClB,GAAG,EAAE,SAAS;IACd,KAAK,EAAE,SAAS;CACjB,CAAC;AAEF,MAAM,QAAQ,GAA2B;IACvC,KAAK,EAAE,YAAY;IACnB,MAAM,EAAE,YAAY;IACpB,KAAK,EAAE,YAAY;IACnB,MAAM,EAAE,YAAY;IACpB,MAAM,EAAE,YAAY;IACpB,MAAM,EAAE,YAAY;IACpB,KAAK,EAAE,QAAQ;IACf,KAAK,EAAE,IAAI;IACX,KAAK,EAAE,MAAM;IACb,KAAK,EAAE,MAAM;IACb,KAAK,EAAE,QAAQ;IACf,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,MAAM;IACf,KAAK,EAAE,QAAQ;IACf,MAAM,EAAE,QAAQ;IAChB,KAAK,EAAE,QAAQ;IACf,QAAQ,EAAE,OAAO;IACjB,KAAK,EAAE,UAAU;IACjB,OAAO,EAAE,MAAM;IACf,MAAM,EAAE,MAAM;IACd,OAAO,EAAE,MAAM;CAChB,CAAC;AAEF,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;AAEvE,MAAM,SAAS,GAAG,CAAC,CAAC;AACpB,MAAM,SAAS,GAAG,MAAM,CAAC;AACzB,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAC9B,MAAM,aAAa,GAAG,EAAE,CAAC;AACzB,MAAM,YAAY,GAAG,EAAE,CAAC;AAExB,MAAM,oBAAqB,SAAQ,KAAK;IACtC;QACE,KAAK,CAAC,0BAA0B,SAAS,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;QACvE,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AASD,SAAS,eAAe,CAAC,IAAY;IACnC,wEAAwE;IACxE,6CAA6C;IAC7C,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACtC,IAAI,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1C,OAAO,KAAK,CAAC;AACf,CAAC;AAED,KAAK,UAAU,IAAI,CACjB,OAAe,EACf,OAAe,EACf,KAAa,EACb,YAA2B,EAC3B,KAAgB;IAEhB,IAAI,KAAK,GAAG,SAAS;QAAE,OAAO;IAC9B,IAAI,OAAiB,CAAC;IACtB,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACP,kEAAkE;QAClE,sEAAsE;QACtE,OAAO;IACT,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC;YAAE,SAAS;QAC1C,MAAM,QAAQ,GAAG,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,OAAO,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;QAC1E,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3C,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,2EAA2E;YAC3E,iEAAiE;YACjE,MAAM,QAAQ,GAAG,KAAK,GAAG,CAAC,CAAC;YAC3B,IACE,QAAQ,IAAI,CAAC;gBACb,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;gBAC9B,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,aAAa;gBACrC,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAClC,CAAC;gBACD,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAChC,CAAC;YACD,MAAM,IAAI,CACR,QAAQ,EACR,QAAQ,EACR,KAAK,GAAG,CAAC,EACT,YAAY,IAAI,KAAK,CAAC,IAAI,EAC1B,KAAK,CACN,CAAC;QACJ,CAAC;aAAM,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;YAC1B,KAAK,CAAC,SAAS,IAAI,CAAC,CAAC;YACrB,IAAI,KAAK,CAAC,SAAS,GAAG,SAAS;gBAAE,MAAM,IAAI,oBAAoB,EAAE,CAAC;YAClE,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;YAC9C,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC;YACxC,KAAK,CAAC,iBAAiB,CAAC,MAAM,CAAC;gBAC7B,CAAC,KAAK,CAAC,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;YAC7C,IAAI,YAAY,KAAK,IAAI,EAAE,CAAC;gBAC1B,KAAK,CAAC,kBAAkB,CAAC,GAAG,CAC1B,YAAY,EACZ,CAAC,KAAK,CAAC,kBAAkB,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CACtD,CAAC;YACJ,CAAC;QACH,CAAC;QACD,uEAAuE;QACvE,kEAAkE;IACpE,CAAC;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY;IAC5B,OAAO,YAAY,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC;AACvC,CAAC;AAED,KAAK,UAAU,iBAAiB,CAAC,OAAe;IAC9C,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAChE,OAAO,OAAO;aACX,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;aAC1D,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,YAAY,GAAa;IACpC,IAAI,EAAE,MAAM;IACZ,KAAK,CAAC,MAAM,CAAC,OAAO;QAClB,MAAM,KAAK,GAAc;YACvB,SAAS,EAAE,CAAC;YACZ,iBAAiB,EAAE,EAAE;YACrB,QAAQ,EAAE,EAAE;YACZ,kBAAkB,EAAE,IAAI,GAAG,EAAE;SAC9B,CAAC;QAEF,sEAAsE;QACtE,uDAAuD;QACvD,IAAI,WAAqB,CAAC;QAC1B,IAAI,CAAC;YACH,WAAW,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAChE,CAAC;QAAC,MAAM,CAAC;YACP,WAAW,GAAG,EAAE,CAAC;QACnB,CAAC;QAED,MAAM,gBAAgB,GAAa,EAAE,CAAC;QACtC,KAAK,MAAM,KAAK,IAAI,WAAW,EAAE,CAAC;YAChC,IAAI,KAAK,CAAC,WAAW,EAAE,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;gBACxD,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACpC,CAAC;QACH,CAAC;QAED,MAAM,IAAI,CAAC,OAAO,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;QAExC,MAAM,YAAY,GAAkB,gBAAgB;aACjD,KAAK,CAAC,CAAC,EAAE,kBAAkB,CAAC;aAC5B,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YACd,IAAI;YACJ,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC;YACxB,SAAS,EAAE,KAAK,CAAC,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;SACnD,CAAC,CAAC,CAAC;QAEN,mEAAmE;QACnE,0DAA0D;QAC1D,MAAM,QAAQ,GAAc,EAAE,CAAC;QAC/B,KAAK,MAAM,GAAG,IAAI,gBAAgB,EAAE,CAAC;YACnC,IAAI,QAAQ,CAAC,GAAG,CAAC,KAAK,UAAU;gBAAE,SAAS;YAC3C,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;YAC7D,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;gBAC7B,IAAI,QAAQ,CAAC,MAAM,IAAI,YAAY;oBAAE,MAAM;gBAC3C,QAAQ,CAAC,IAAI,CAAC;oBACZ,IAAI,EAAE,KAAK;oBACX,IAAI,EAAE,GAAG,GAAG,IAAI,KAAK,EAAE;oBACvB,KAAK,EAAE,IAAI;iBACZ,CAAC,CAAC;YACL,CAAC;YACD,IAAI,QAAQ,CAAC,MAAM,IAAI,YAAY;gBAAE,MAAM;QAC7C,CAAC;QAED,OAAO;YACL,IAAI,EAAE;gBACJ,YAAY;gBACZ,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;gBAC1C,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,aAAa,CAAC;gBAChD,SAAS,EAAE,KAAK,CAAC,SAAS;aAC3B;YACD,QAAQ;SACT,CAAC;IACJ,CAAC;CACF,CAAC"}
@@ -0,0 +1,29 @@
1
+ import { type MergeResult } from "./writers/merge.js";
2
+ import { type SkipResult } from "./writers/skip.js";
3
+ import type { ScaffoldPlan } from "./scaffold-schema.js";
4
+ export type ApplyMode = "dry-run" | "apply";
5
+ export interface EmitResult {
6
+ path: string;
7
+ action: "emit";
8
+ wrote: boolean;
9
+ }
10
+ export type ApplyFileResult = EmitResult | MergeResult | SkipResult;
11
+ export interface ApplyResult {
12
+ mode: ApplyMode;
13
+ results: ApplyFileResult[];
14
+ rendered?: string;
15
+ }
16
+ export interface ApplyOptions {
17
+ mode: ApplyMode;
18
+ force?: boolean;
19
+ color?: boolean;
20
+ stderr?: (s: string) => void;
21
+ }
22
+ export declare class ScaffoldApplyError extends Error {
23
+ written: string[];
24
+ notWritten: string[];
25
+ cause: unknown;
26
+ constructor(message: string, written: string[], notWritten: string[], cause: unknown);
27
+ }
28
+ export declare function applyPlan(rootDir: string, plan: ScaffoldPlan, opts: ApplyOptions): Promise<ApplyResult>;
29
+ //# sourceMappingURL=apply-plan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apply-plan.d.ts","sourceRoot":"","sources":["../../src/onboard/apply-plan.ts"],"names":[],"mappings":"AAcA,OAAO,EAAc,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,EAAa,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAG/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AAE5C,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,WAAW,GAAG,UAAU,CAAC;AAEpE,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9B;AAED,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,MAAM,EAAE,CAAC;IACZ,KAAK,EAAE,OAAO,CAAC;gBACZ,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,OAAO;CAOrF;AAED,wBAAsB,SAAS,CAC7B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,YAAY,EAClB,IAAI,EAAE,YAAY,GACjB,OAAO,CAAC,WAAW,CAAC,CAuDtB"}
@@ -0,0 +1,80 @@
1
+ // packages/cli/src/onboard/apply-plan.ts
2
+ //
3
+ // Dispatcher over the three writers + the dry-run renderer. The PR writer
4
+ // is a separate entry point (pr-writer.ts) because it spans subprocess
5
+ // orchestration (gh auth check + branch + commit + gh pr create) that
6
+ // doesn't belong in this hot path.
7
+ //
8
+ // Partial-failure contract (per B-D7): on any write error mid-loop, collect
9
+ // the written-so-far list + the not-written list and re-throw a
10
+ // ScaffoldApplyError. Idempotency: callers can re-run --apply after fixing
11
+ // the disk/permission issue; written files are overwritten with identical
12
+ // content; merge files re-detect the BEGIN/END block.
13
+ import { writeEmit } from "./writers/emit.js";
14
+ import { writeMerge } from "./writers/merge.js";
15
+ import { writeSkip } from "./writers/skip.js";
16
+ import { renderDryRun } from "./writers/dry-run-renderer.js";
17
+ export class ScaffoldApplyError extends Error {
18
+ written;
19
+ notWritten;
20
+ cause;
21
+ constructor(message, written, notWritten, cause) {
22
+ super(message);
23
+ this.name = "ScaffoldApplyError";
24
+ this.written = written;
25
+ this.notWritten = notWritten;
26
+ this.cause = cause;
27
+ }
28
+ }
29
+ export async function applyPlan(rootDir, plan, opts) {
30
+ if (opts.mode !== "dry-run" && opts.mode !== "apply") {
31
+ throw new Error(`df onboard: applyPlan does not handle mode "${opts.mode}". ` +
32
+ "For pr mode, use runPrMode(plan, ...) from pr-writer.ts.");
33
+ }
34
+ if (opts.mode === "dry-run") {
35
+ const renderOpts = opts.color !== undefined ? { color: opts.color } : {};
36
+ const rendered = await renderDryRun(rootDir, plan, renderOpts);
37
+ const results = plan.files.map((f) => {
38
+ if (f.action === "skip")
39
+ return { path: f.path, action: "skip", rationale: f.rationale, wrote: false };
40
+ if (f.action === "emit")
41
+ return { path: f.path, action: "emit", wrote: false };
42
+ return { path: f.path, action: "merge", wrote: false, skipped: false };
43
+ });
44
+ return { mode: "dry-run", results, rendered };
45
+ }
46
+ // apply mode
47
+ const results = [];
48
+ const written = [];
49
+ for (let i = 0; i < plan.files.length; i++) {
50
+ const file = plan.files[i];
51
+ try {
52
+ if (file.action === "skip") {
53
+ results.push(await writeSkip(rootDir, file));
54
+ continue;
55
+ }
56
+ if (file.action === "emit") {
57
+ await writeEmit(rootDir, file, { force: opts.force ?? false });
58
+ results.push({ path: file.path, action: "emit", wrote: true });
59
+ written.push(file.path);
60
+ continue;
61
+ }
62
+ // merge
63
+ const mergeOpts = opts.stderr !== undefined ? { stderr: opts.stderr } : {};
64
+ const r = await writeMerge(rootDir, file, mergeOpts);
65
+ results.push(r);
66
+ if (r.wrote)
67
+ written.push(file.path);
68
+ }
69
+ catch (err) {
70
+ const notWritten = plan.files.slice(i).map((f) => f.path);
71
+ throw new ScaffoldApplyError(`df onboard: write failed at ${file.path} (${err instanceof Error ? err.message : String(err)}). ` +
72
+ `Files written before the failure: ${written.length ? written.join(", ") : "(none)"}. ` +
73
+ `Files NOT written: ${notWritten.join(", ")}. ` +
74
+ `Re-run \`df onboard --apply\` after addressing the disk/perm issue; ` +
75
+ `written files will be overwritten with the same content (idempotent).`, written, notWritten, err);
76
+ }
77
+ }
78
+ return { mode: "apply", results };
79
+ }
80
+ //# sourceMappingURL=apply-plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apply-plan.js","sourceRoot":"","sources":["../../src/onboard/apply-plan.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { RepoAnalysis } from "./schema.js";
2
+ export declare function autoProfile(analysis: RepoAnalysis): "local" | "cloud";
3
+ //# sourceMappingURL=auto-profile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-profile.d.ts","sourceRoot":"","sources":["../../src/onboard/auto-profile.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,wBAAgB,WAAW,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,GAAG,OAAO,CAGrE"}
@@ -0,0 +1,20 @@
1
+ // packages/cli/src/onboard/auto-profile.ts
2
+ //
3
+ // Resolve the critic profile (local | cloud) from a RepoAnalysis when the
4
+ // operator did not pass --profile explicitly.
5
+ //
6
+ // This module is shipped as its own file (not inline in commands/onboard.ts)
7
+ // so Phase C's deterministic .agent-review/config.json seeder can import the
8
+ // same function via `import { autoProfile } from "../auto-profile.js"`. The
9
+ // single-source-of-truth keeps Phase B + Phase C aligned on the heuristic
10
+ // without either side re-implementing it.
11
+ //
12
+ // Heuristic (B-D8): a repo that already has a DF cli-pin AND a cloud PR
13
+ // workflow is one that already runs the cloud quartet — keep them on
14
+ // `cloud`. Everything else defaults to `local`. Explicit `--profile` always
15
+ // wins; this function is only the fallback.
16
+ export function autoProfile(analysis) {
17
+ const dfWired = analysis.dfPresence.cliPin !== null && analysis.dfPresence.prWorkflow;
18
+ return dfWired ? "cloud" : "local";
19
+ }
20
+ //# sourceMappingURL=auto-profile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-profile.js","sourceRoot":"","sources":["../../src/onboard/auto-profile.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAC3C,EAAE;AACF,0EAA0E;AAC1E,8CAA8C;AAC9C,EAAE;AACF,6EAA6E;AAC7E,6EAA6E;AAC7E,4EAA4E;AAC5E,0EAA0E;AAC1E,0CAA0C;AAC1C,EAAE;AACF,wEAAwE;AACxE,qEAAqE;AACrE,4EAA4E;AAC5E,4CAA4C;AAI5C,MAAM,UAAU,WAAW,CAAC,QAAsB;IAChD,MAAM,OAAO,GAAG,QAAQ,CAAC,UAAU,CAAC,MAAM,KAAK,IAAI,IAAI,QAAQ,CAAC,UAAU,CAAC,UAAU,CAAC;IACtF,OAAO,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;AACrC,CAAC"}
@@ -0,0 +1,20 @@
1
+ export interface GitHistoryFixture {
2
+ canonical: string;
3
+ defaultBranch: string;
4
+ remote: string;
5
+ subjects: string[];
6
+ }
7
+ export declare function parseGitHistory(body: string): GitHistoryFixture;
8
+ /**
9
+ * Initialize `<repoDir>` as a real git repo with the fixture's remote and
10
+ * default-branch metadata, then replay the subjects as empty commits over
11
+ * an initial commit that captures whatever files already exist in repoDir.
12
+ *
13
+ * After this returns the git analyzer will see:
14
+ * - a real .git dir
15
+ * - an origin remote (so canonicalName parses)
16
+ * - the right default branch
17
+ * - up to 200 subjects via `git log --pretty=%s` (oldest → newest)
18
+ */
19
+ export declare function replayGitHistory(repoDir: string, fixture: GitHistoryFixture): Promise<void>;
20
+ //# sourceMappingURL=replay-git-history.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay-git-history.d.ts","sourceRoot":"","sources":["../../../src/onboard/fixtures/replay-git-history.ts"],"names":[],"mappings":"AAyBA,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,CA0B/D;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,IAAI,CAAC,CAkCf"}