arkgate 3.7.0 → 3.8.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 (77) hide show
  1. package/CHANGELOG.md +76 -1145
  2. package/README.md +59 -19
  3. package/bin/ark-check-runtime.mjs +1598 -0
  4. package/bin/ark-check.mjs +32 -1565
  5. package/bin/ark-mcp-runtime.mjs +1976 -0
  6. package/bin/ark-mcp.mjs +84 -1495
  7. package/bin/ark-shared.mjs +34 -38
  8. package/bin/ark.mjs +33 -66
  9. package/bin/lib/adapter-contract.mjs +161 -9
  10. package/bin/lib/agent-gates.mjs +1 -0
  11. package/bin/lib/analysis-completeness.mjs +28 -0
  12. package/bin/lib/analysis-engine.mjs +8 -8
  13. package/bin/lib/analysis-policy.mjs +27 -0
  14. package/bin/lib/architecture-scan.mjs +70 -357
  15. package/bin/lib/auto-patch.mjs +76 -8
  16. package/bin/lib/ci-and-commands.mjs +1 -1
  17. package/bin/lib/codex-home.mjs +43 -16
  18. package/bin/lib/design-delta.mjs +4 -0
  19. package/bin/lib/doctor-advisories.mjs +4 -3
  20. package/bin/lib/doctor-plan.mjs +40 -41
  21. package/bin/lib/enforcement-state.mjs +2 -0
  22. package/bin/lib/github-enforcement.mjs +443 -0
  23. package/bin/lib/hook-templates.mjs +12 -148
  24. package/bin/lib/html-report-advisories.mjs +1 -1
  25. package/bin/lib/html-report-depth.mjs +9 -0
  26. package/bin/lib/html-report.mjs +5 -5
  27. package/bin/lib/install-migrate.mjs +83 -79
  28. package/bin/lib/managed-upgrade.mjs +622 -0
  29. package/bin/lib/mcp-adoption.mjs +3 -1
  30. package/bin/lib/parse-health.mjs +6 -5
  31. package/bin/lib/port-proof.mjs +2 -2
  32. package/bin/lib/prepare-change.mjs +68 -38
  33. package/bin/lib/prepare-write.mjs +7 -1
  34. package/bin/lib/resident-doctor-client.mjs +55 -0
  35. package/bin/lib/resident-hook.mjs +247 -0
  36. package/bin/lib/resolved-candidate-facts.mjs +1160 -0
  37. package/bin/lib/scan-files.mjs +19 -6
  38. package/bin/lib/snippet-analysis.mjs +119 -0
  39. package/bin/lib/source-policy.mjs +24 -0
  40. package/bin/lib/typescript-host.mjs +15 -18
  41. package/bin/lib/unavailable-analysis.mjs +76 -0
  42. package/bin/lib/upgrade-command.mjs +115 -0
  43. package/bin/lib/weakest-link.mjs +21 -179
  44. package/bin/lib/write-path-capabilities.mjs +167 -16
  45. package/bin/lib/write-path-detect.mjs +3 -2
  46. package/dist/eslint/index.cjs +3 -3
  47. package/dist/eslint/index.d.ts +3 -0
  48. package/dist/eslint/index.js +3 -3
  49. package/dist/index.cjs +7 -7
  50. package/dist/index.d.ts +1073 -141
  51. package/dist/index.js +7 -7
  52. package/docs/agent-guide.md +103 -59
  53. package/docs/ai-gates.md +97 -16
  54. package/docs/demos/01-write-gate-self-correction.md +2 -2
  55. package/docs/enthusiast/README.md +10 -10
  56. package/docs/enthusiast/how-to-gallery-starter.md +2 -2
  57. package/docs/enthusiast/reference-commands.md +18 -1
  58. package/docs/enthusiast/tutorial-first-project.md +2 -2
  59. package/docs/package-surface.md +98 -12
  60. package/docs/typescript-support.md +109 -37
  61. package/package.json +32 -4
  62. package/schemas/ark.analysis-result.schema.json +159 -2
  63. package/schemas/ark.design-delta.schema.json +1 -0
  64. package/schemas/ark.enforcement-state.schema.json +84 -0
  65. package/schemas/ark.resolved-candidate-facts.schema.json +1 -0
  66. package/server.json +2 -2
  67. package/templates/skills/ark-explore.md +5 -5
  68. package/templates/skills/ark-fix.md +1 -1
  69. package/templates/skills/ark-runtime.md +15 -8
  70. package/templates/skills/ark-upgrade.md +122 -182
  71. package/bin/lib/ai-velocity.mjs +0 -293
  72. package/bin/lib/graph-cycles.mjs +0 -6
  73. package/bin/lib/safety-diagnostics.mjs +0 -284
  74. package/bin/lib/ts-resolve.mjs +0 -228
  75. package/dist/configTypes-DAPvBqK6.d.cts +0 -61
  76. package/dist/eslint/index.d.cts +0 -146
  77. package/dist/index.d.cts +0 -986
@@ -125,6 +125,81 @@ export function warnLockfileConflict(root) {
125
125
  );
126
126
  }
127
127
 
128
+ /**
129
+ * Canonical, side-effect-free catalog of project assets emitted by the gate installer.
130
+ * Upgrade consumes this same allowlist; a manifest can record identities but can never
131
+ * introduce a new write path.
132
+ */
133
+ export function buildManagedAssetCatalog({ root, tools, compact = false, skillsOnly = false }) {
134
+ const selectedTools = tools instanceof Set ? tools : new Set(tools ?? []);
135
+ const assets = [];
136
+ const add = (relativePath, content, kind = 'gate', scope = 'whole-file') => {
137
+ assets.push({
138
+ relativePath,
139
+ content,
140
+ kind,
141
+ scope,
142
+ templateId: `${kind}:${relativePath}`,
143
+ });
144
+ };
145
+
146
+ if (!skillsOnly) {
147
+ const compactHost = compact ? [...selectedTools][0] ?? null : null;
148
+ add(
149
+ 'AGENTS.md',
150
+ compact ? compactAgentInstructions(root, compactHost) : agentInstructions(root)
151
+ );
152
+ if (!compact || !compactHost || compactHost === 'claude') add('.mcp.json', mcpJson(root));
153
+ const deploy = detectDeployPathQuality(root);
154
+ add(
155
+ '.github/workflows/ark-check.yml',
156
+ githubWorkflow(packageManager(root), detectCiNode(root), {
157
+ hasLintScript: deploy.hasLintScript,
158
+ hasTypecheckScript: deploy.hasTypecheckScript,
159
+ })
160
+ );
161
+ if (selectedTools.has('cursor')) {
162
+ add('.cursor/mcp.json', mcpJson(root));
163
+ if (!compact) add('.cursor/rules/ark.mdc', cursorRule(root));
164
+ }
165
+ if (selectedTools.has('claude')) add('.claude/settings.json', claudeSettings(root));
166
+ if (selectedTools.has('codex')) {
167
+ add('.codex/hooks.json', codexHooks(root));
168
+ add('.codex/config.toml', codexProjectConfig(root), 'gate', 'toml-section');
169
+ if (!compact) add('docs/ark-codex-config.toml', codexTomlSnippet(root));
170
+ }
171
+ if (selectedTools.has('grok')) {
172
+ add('.grok/config.toml', grokProjectConfig(root));
173
+ add('.grok/hooks/ark-write-gate.json', grokHooks(root));
174
+ }
175
+ if (selectedTools.has('windsurf')) add('.windsurf/rules/ark.md', instructionRule(root));
176
+ if (selectedTools.has('cline')) add('.clinerules/ark.md', instructionRule(root));
177
+ if (selectedTools.has('copilot')) {
178
+ add('.github/copilot-instructions.md', instructionRule(root));
179
+ }
180
+ if (selectedTools.has('kiro')) add('.kiro/steering/ark.md', instructionRule(root));
181
+ if (selectedTools.has('roo')) add('.roo/rules/ark.md', instructionRule(root));
182
+ if (selectedTools.has('continue')) add('.continue/rules/ark.md', instructionRule(root));
183
+ if (selectedTools.has('gemini')) add('GEMINI.md', instructionRule(root));
184
+ }
185
+
186
+ const version = arkPackageVersion();
187
+ const skills = skillTemplates().map(([name, content]) => [name, stampSkill(content, version)]);
188
+ const skillPaths = new Set();
189
+ if (!compact) {
190
+ for (const tool of selectedTools) {
191
+ const target = SKILL_TOOL_TARGETS[tool];
192
+ if (!target) continue;
193
+ for (const [name, content] of skills) {
194
+ const relativePath = target(name);
195
+ skillPaths.add(relativePath);
196
+ add(relativePath, content, 'skill');
197
+ }
198
+ }
199
+ }
200
+ return { assets, skills, skillPaths, version };
201
+ }
202
+
128
203
  // --migrate-commands: rewrite ONLY the Ark command runner in existing gate files to the
129
204
  // project's package manager (no --force clobber). Closes the upgrade gap where a repo that
130
205
  // adopted before the package-manager-aware templates keeps a stale `npx`.
@@ -220,7 +295,6 @@ export function runInstallAgentGates(args) {
220
295
  process.exitCode = 2;
221
296
  return;
222
297
  }
223
- const pm = packageManager(root);
224
298
  const hasCheckScript = hasCheckArchitectureScript(root);
225
299
  const { tools, source } = args.compact && args.tools == null
226
300
  ? { tools: new Set(), source: 'compact-none' }
@@ -239,7 +313,6 @@ export function runInstallAgentGates(args) {
239
313
  ? 'no active host detected'
240
314
  : 'default set — no agent config dirs found';
241
315
  console.log(`Agent gates for: ${[...tools].sort().join(', ')} (${toolSource})`);
242
- const templates = [];
243
316
  // --skills-only refreshes just the canonical /ark-* skills, which are safe to
244
317
  // overwrite (they track the package). The gate/instruction files (AGENTS.md,
245
318
  // settings.json, CI workflow, rules) are the ones users customize, so a plain
@@ -253,84 +326,15 @@ export function runInstallAgentGates(args) {
253
326
  `Added package.json script "typecheck": "${typecheckBootstrap.script}" (tsconfig present; local/CI parity).`
254
327
  );
255
328
  }
256
- // Base gates: tool-agnostic contract + CI backstop, always written.
257
- const compactHost = args.compact ? [...tools][0] ?? null : null;
258
- templates.push([
259
- 'AGENTS.md',
260
- args.compact ? compactAgentInstructions(root, compactHost) : agentInstructions(root),
261
- ]);
262
- if (!args.compact || !compactHost || compactHost === 'claude') {
263
- templates.push(['.mcp.json', mcpJson(root)]);
264
- }
265
- templates.push([
266
- '.github/workflows/ark-check.yml',
267
- (() => {
268
- const deploy = detectDeployPathQuality(root);
269
- return githubWorkflow(pm, detectCiNode(root), {
270
- hasLintScript: deploy.hasLintScript,
271
- hasTypecheckScript: deploy.hasTypecheckScript,
272
- });
273
- })(),
274
- ]);
275
- if (tools.has('cursor')) {
276
- templates.push(['.cursor/mcp.json', mcpJson(root)]);
277
- if (!args.compact) templates.push(['.cursor/rules/ark.mdc', cursorRule(root)]);
278
- }
279
- if (tools.has('claude')) {
280
- templates.push(['.claude/settings.json', claudeSettings(root)]);
281
- }
282
- if (tools.has('codex')) {
283
- templates.push(['.codex/hooks.json', codexHooks(root)]);
284
- templates.push(['.codex/config.toml', codexProjectConfig(root)]);
285
- if (!args.compact) templates.push(['docs/ark-codex-config.toml', codexTomlSnippet(root)]);
286
- }
287
- if (tools.has('grok')) {
288
- templates.push(['.grok/config.toml', grokProjectConfig(root)]);
289
- templates.push(['.grok/hooks/ark-write-gate.json', grokHooks(root)]);
290
- }
291
- // Instruction-tier hosts: one shared rule text, host-specific path.
292
- if (tools.has('windsurf')) {
293
- templates.push(['.windsurf/rules/ark.md', instructionRule(root)]);
294
- }
295
- if (tools.has('cline')) {
296
- templates.push(['.clinerules/ark.md', instructionRule(root)]);
297
- }
298
- if (tools.has('copilot')) {
299
- templates.push(['.github/copilot-instructions.md', instructionRule(root)]);
300
- }
301
- if (tools.has('kiro')) {
302
- templates.push(['.kiro/steering/ark.md', instructionRule(root)]);
303
- }
304
- if (tools.has('roo')) {
305
- templates.push(['.roo/rules/ark.md', instructionRule(root)]);
306
- }
307
- if (tools.has('continue')) {
308
- templates.push(['.continue/rules/ark.md', instructionRule(root)]);
309
- }
310
- // Gemini CLI reads GEMINI.md as its primary project context (it also reads
311
- // AGENTS.md, but GEMINI.md wins when both are present), so the rule lives there.
312
- if (tools.has('gemini')) {
313
- templates.push(['GEMINI.md', instructionRule(root)]);
314
- }
315
- }
316
- // /ark-* skills for every detected tool that supports project-level commands.
317
- // Stamp each with the shipping version so a later ark-check can flag skills
318
- // left behind by an older Ark (see detectSkillGaps) without nagging about
319
- // user edits to the body.
320
- const version = arkPackageVersion();
321
- const skills = skillTemplates().map(([name, content]) => [name, stampSkill(content, version)]);
322
- const skillPaths = new Set();
323
- if (!args.compact) {
324
- for (const tool of tools) {
325
- const target = SKILL_TOOL_TARGETS[tool];
326
- if (!target) continue;
327
- for (const [name, content] of skills) {
328
- const relativePath = target(name);
329
- skillPaths.add(relativePath);
330
- templates.push([relativePath, content]);
331
- }
332
- }
333
329
  }
330
+ const catalog = buildManagedAssetCatalog({
331
+ root,
332
+ tools,
333
+ compact: args.compact,
334
+ skillsOnly: args.skillsOnly,
335
+ });
336
+ const { skills, skillPaths, version } = catalog;
337
+ const templates = catalog.assets.map(({ relativePath, content }) => [relativePath, content]);
334
338
 
335
339
  // A compact router can be moved back from an explicit host removal. Delete the
336
340
  // generic MCP file only when it exactly matches Ark's generated artifact.