arkgate 4.6.0 → 4.6.2

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 (78) hide show
  1. package/CHANGELOG.md +54 -1
  2. package/README.md +11 -5
  3. package/bin/ark-check-runtime.mjs +115 -128
  4. package/bin/ark-mcp-runtime.mjs +86 -48
  5. package/bin/ark.mjs +21 -78
  6. package/bin/lib/agent-projection.mjs +1 -1
  7. package/bin/lib/analysis-engine.mjs +3 -3
  8. package/bin/lib/ci-and-commands.mjs +11 -11
  9. package/bin/lib/config-contract.mjs +2 -0
  10. package/bin/lib/contract-smells.mjs +5 -5
  11. package/bin/lib/design-smells.mjs +1 -1
  12. package/bin/lib/doctor-advisories.mjs +9 -0
  13. package/bin/lib/doctor-next-actions.mjs +92 -0
  14. package/bin/lib/doctor-plan.mjs +61 -71
  15. package/bin/lib/field-install.mjs +1 -1
  16. package/bin/lib/first-run-help.mjs +221 -0
  17. package/bin/lib/html-report-advisories.mjs +20 -0
  18. package/bin/lib/improvement-compass-map.mjs +20 -20
  19. package/bin/lib/pilot-loop.mjs +1 -1
  20. package/bin/lib/post-green-path.mjs +2 -2
  21. package/bin/lib/prepare-change.mjs +9 -0
  22. package/bin/lib/product-copy.mjs +1 -1
  23. package/bin/lib/start-preview.mjs +17 -10
  24. package/bin/lib/status-command.mjs +19 -0
  25. package/bin/lib/status-manifest.mjs +23 -0
  26. package/bin/lib/team-parliament-io.mjs +338 -0
  27. package/bin/lib/team-parliament.mjs +383 -0
  28. package/bin/lib/upgrade-whats-new.mjs +16 -0
  29. package/bin/lib/violations.mjs +8 -4
  30. package/dist/{configTypes-CC0FEXoF.d.ts → configTypes-B8uIcLaG.d.ts} +5 -0
  31. package/dist/eslint/index.cjs +2 -2
  32. package/dist/eslint/index.d.ts +1 -1
  33. package/dist/eslint/index.js +2 -2
  34. package/dist/index.cjs +8 -8
  35. package/dist/index.d.ts +66 -2
  36. package/dist/index.js +8 -8
  37. package/docs/README.md +5 -5
  38. package/docs/agent-guide.md +21 -17
  39. package/docs/configuration.md +36 -2
  40. package/docs/develop.md +13 -1
  41. package/docs/enthusiast/README.md +1 -1
  42. package/docs/enthusiast/how-to-agent-gates.md +3 -3
  43. package/docs/enthusiast/how-to-pick-shape.md +2 -2
  44. package/docs/enthusiast/tutorial-first-project.md +4 -3
  45. package/docs/package-surface.md +5 -3
  46. package/docs/product-voice.md +48 -10
  47. package/docs/use.md +10 -5
  48. package/package.json +2 -2
  49. package/schemas/ark.config.schema.json +9 -0
  50. package/schemas/ark.status-manifest.schema.json +51 -0
  51. package/server.json +3 -3
  52. package/templates/agent-skills/README.md +1 -1
  53. package/templates/agent-skills/ark-adopt/SKILL.md +59 -23
  54. package/templates/agent-skills/ark-architect/SKILL.md +24 -145
  55. package/templates/agent-skills/ark-autopilot/SKILL.md +49 -32
  56. package/templates/agent-skills/ark-contract/SKILL.md +21 -105
  57. package/templates/agent-skills/ark-coverage/SKILL.md +7 -3
  58. package/templates/agent-skills/ark-explain/SKILL.md +8 -4
  59. package/templates/agent-skills/ark-explore/SKILL.md +38 -21
  60. package/templates/agent-skills/ark-fix/SKILL.md +34 -157
  61. package/templates/agent-skills/ark-loop/SKILL.md +31 -153
  62. package/templates/agent-skills/ark-place/SKILL.md +35 -14
  63. package/templates/agent-skills/ark-runtime/SKILL.md +3 -3
  64. package/templates/agent-skills/ark-think/SKILL.md +6 -2
  65. package/templates/agent-skills/ark-upgrade/SKILL.md +21 -10
  66. package/templates/skills/ark-adopt.md +59 -23
  67. package/templates/skills/ark-architect.md +24 -145
  68. package/templates/skills/ark-autopilot.md +49 -32
  69. package/templates/skills/ark-contract.md +21 -105
  70. package/templates/skills/ark-coverage.md +7 -3
  71. package/templates/skills/ark-explain.md +8 -4
  72. package/templates/skills/ark-explore.md +38 -21
  73. package/templates/skills/ark-fix.md +34 -157
  74. package/templates/skills/ark-loop.md +31 -153
  75. package/templates/skills/ark-place.md +35 -14
  76. package/templates/skills/ark-runtime.md +3 -3
  77. package/templates/skills/ark-think.md +6 -2
  78. package/templates/skills/ark-upgrade.md +21 -10
@@ -19,6 +19,7 @@ import {
19
19
  import { printParseHealthSection, summarizeParseHealth } from './parse-health.mjs';
20
20
  import { detectGraphBlindSpots, printGraphBlindSection } from './graph-blind.mjs';
21
21
  import { summarizeRulesUnderContract } from './rules-under-contract.mjs';
22
+ import { collectStewardNudge } from './team-parliament-io.mjs';
22
23
 
23
24
  export function computeDoctorAdvisories(root, config, cov, rules, files, ts, parseHealth, facts) {
24
25
  const physicalCohesion = computePhysicalCohesion(root, files);
@@ -49,6 +50,7 @@ export function computeDoctorAdvisories(root, config, cov, rules, files, ts, par
49
50
  graphBlindSpots: detectGraphBlindSpots(ts, root, files),
50
51
  // AR12 — Rules under contract (honest counts; real test I/O, never empty-fileContents stub).
51
52
  // P1M: pass classification so extraMergeTeeth cannot arm at 0% governed.
53
+ stewardNudge: collectStewardNudge(root, config),
52
54
  rulesUnderContract: summarizeRulesUnderContract(root, config, factPaths, {
53
55
  governedPercent: cov?.governed?.percent ?? null,
54
56
  populatedLayerCount: Array.isArray(cov?.layers)
@@ -70,4 +72,11 @@ export function printDoctorAdvisories(advisories, io) {
70
72
  printReshapeDecisionsSection(advisories.physicalCohesion?.reshapeDecisions, io);
71
73
  printParseHealthSection(advisories.parseHealth, io);
72
74
  printGraphBlindSection(advisories.graphBlindSpots, io);
75
+ const nudge = advisories.stewardNudge;
76
+ if ((nudge?.needsStewards || nudge?.drift) && nudge.ask) {
77
+ console.log('');
78
+ console.log(io.color.bold('Stewards (advisory)'));
79
+ io.line(io.warn, nudge.ask);
80
+ if (nudge.nextAction) io.line(' ', io.color.dim(`Next: ${nudge.nextAction}`));
81
+ }
73
82
  }
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Rank doctor next actions from already-computed facts (no I/O).
3
+ * Lets the human printer show light + #1 before honesty/compass sections.
4
+ */
5
+ import { arkCommand } from '../ark-shared.mjs';
6
+ import { skillGapsForActiveHost } from './agent-gates.mjs';
7
+ import { agentHomeConcernIsActive, agentHomeRefreshCommand } from './agent-homes.mjs';
8
+ import { mergePostGreenTopActions } from './post-green-path.mjs';
9
+
10
+ export function collectDoctorNextActions(ctx) {
11
+ const actions = [];
12
+ if (!ctx.analysisComplete) actions.push('restore complete analysis, then rerun ark-check --doctor');
13
+ if (ctx.designSmells.length > 0 && ctx.postGreenPath) actions.push(ctx.postGreenPath.action);
14
+ if (ctx.coverageHonesty.greenIsNotEnforcement && ctx.coverageHonesty.worseThanNoGate) {
15
+ actions.push('raise governed coverage above a minority slice before treating green as enforcement');
16
+ }
17
+ if (ctx.cov.suggestions.length > 0) actions.push('classify the ungoverned directories (/ark-adopt)');
18
+ if (ctx.packageVersionTruth?.dualTruth) {
19
+ actions.push(
20
+ ctx.dualTruthNext ||
21
+ 'bump package.json arkgate pin to match this CLI (or install without --no-install)'
22
+ );
23
+ } else if (ctx.packageVersionTruth?.code === 'PACKAGE_PIN_ABSENT') {
24
+ actions.push(
25
+ ctx.dualTruthNext ||
26
+ 'Add arkgate to package.json and install so CI/npx resolve this CLI (PACKAGE_PIN_ABSENT)'
27
+ );
28
+ }
29
+ if (ctx.activeCount > 0) {
30
+ actions.push(
31
+ `resolve the non-baselined violations — see the classified plan (${arkCommand(ctx.root, 'ark-check', '--plan')}), then /ark-autopilot`
32
+ );
33
+ }
34
+ if (ctx.writePath?.gap?.fix) actions.push(ctx.writePath.gap.fix);
35
+ if (ctx.gatesMissing.length > 0) {
36
+ actions.push(`install gates (${arkCommand(ctx.root, 'ark-check', '--install-agent-gates')})`);
37
+ }
38
+ const humanSkillGaps = skillGapsForActiveHost(ctx.skillGaps);
39
+ const legacyCodex = humanSkillGaps.some((g) => g.tool === 'codex' && g.legacyPromptsOnly);
40
+ const remainingGaps = humanSkillGaps.filter(
41
+ (g) => !(g.tool === 'codex' && (g.legacyPromptsOnly || g.legacyAdvisory))
42
+ );
43
+ const remMiss = remainingGaps.reduce((s, g) => s + g.missing, 0);
44
+ const remStale = remainingGaps.reduce((s, g) => s + g.stale, 0);
45
+ if (legacyCodex) {
46
+ actions.push('install Codex SKILL.md catalog (--install-agent-gates --skills-only --tools codex --force)');
47
+ }
48
+ if (remMiss + remStale > 0) {
49
+ actions.push('refresh /ark-* skills (--install-agent-gates --skills-only --force)');
50
+ }
51
+ if (ctx.codexHomeGap && ctx.codexConcernActive) {
52
+ actions.push(
53
+ ctx.codexHomeGap.catalogMetadataInvalid
54
+ ? 'repair invalid Codex home catalog metadata after verifying the newest installed version'
55
+ : 'refresh Codex home skills (--install-agent-gates --skills-only --codex-home --force)'
56
+ );
57
+ }
58
+ for (const gap of ctx.agentHomeGaps) {
59
+ if (agentHomeConcernIsActive(gap.host)) {
60
+ actions.push(
61
+ gap.catalogMetadataInvalid
62
+ ? `repair invalid ${gap.label} home catalog metadata after verifying the newest installed version`
63
+ : `refresh ${gap.label} shared agent skills (${agentHomeRefreshCommand(ctx.root, gap)})`
64
+ );
65
+ }
66
+ }
67
+ if (ctx.analysisComplete && ctx.baselineHonesty?.dirtyBaselineRisk) {
68
+ actions.push('review dirty baseline freezes — fix the contract before trusting green-via-freeze');
69
+ }
70
+ if (ctx.analysisComplete && ctx.staleBaseline > 0) {
71
+ actions.push('tighten the baseline (--update-baseline)');
72
+ }
73
+ if (ctx.staleRunners.length > 0) {
74
+ actions.push(
75
+ `migrate command runners (${arkCommand(ctx.root, 'ark-check', '--install-agent-gates --migrate-commands')})`
76
+ );
77
+ }
78
+ for (const gap of ctx.adoption.gaps) {
79
+ if (!gap.deferred) actions.push(gap.fix || gap.message);
80
+ }
81
+ if (ctx.safety && ctx.safetyHasEntries) {
82
+ actions.push('resolve strict safety diagnostics before treating CI as enforcement');
83
+ }
84
+ if (ctx.showNewHere) {
85
+ actions.unshift('finish ark start (preview + --apply), then re-run --doctor');
86
+ }
87
+ const unique = mergePostGreenTopActions(actions, ctx.postGreenPath);
88
+ if (ctx.designFitness.designWeak && unique.length === 0 && ctx.postGreenPath) {
89
+ unique.push(ctx.postGreenPath.action);
90
+ }
91
+ return unique;
92
+ }
@@ -15,9 +15,9 @@ import { describePackageVersionDualTruth } from './field-install.mjs';
15
15
  import {
16
16
  detectAgentHomeGaps,
17
17
  agentHomeConcernIsActive,
18
- agentHomeRefreshCommand,
19
18
  } from './agent-homes.mjs';
20
19
  import { operatingModeTitle } from './product-copy.mjs';
20
+ import { collectDoctorNextActions } from './doctor-next-actions.mjs';
21
21
  export { summarizeRulesUnderContract };
22
22
 
23
23
  /** Optional S3 dual-match classifier when ark-shared exports it (soft dep for S5 landing). */
@@ -50,7 +50,6 @@ import {
50
50
  } from './design-smells.mjs';
51
51
  import {
52
52
  buildPostGreenNextAction,
53
- mergePostGreenTopActions,
54
53
  isDoctorHealthyNothingToDo,
55
54
  DESIGN_WEAK_HONESTY_FLAGS,
56
55
  } from './post-green-path.mjs';
@@ -208,7 +207,7 @@ export function runCoverage(root, config, files, rules, asJson) {
208
207
  }
209
208
  }
210
209
  console.log('');
211
- console.log('Apply these via /ark-contract (adds the layer patterns to ark.config.json).');
210
+ console.log('Apply these via /ark-adopt (adds the layer patterns to ark.config.json).');
212
211
  }
213
212
  if (layersWithoutRules.length > 0) {
214
213
  console.log('');
@@ -825,9 +824,7 @@ export function runDoctor(root, config, files, rules, violations, asJson, option
825
824
  const ok = color.green('✓');
826
825
  const warn = color.yellow('!');
827
826
  const bad = color.red('✗');
828
- const actions = [];
829
827
  const line = (mark, text) => console.log(` ${mark} ${text}`);
830
- if (!analysisComplete) actions.push('restore complete analysis, then rerun ark-check --doctor');
831
828
  console.log(color.bold(`Ark doctor — ${path.basename(path.resolve(root)) || '.'}`));
832
829
  if (!analysisComplete) line(warn, analysisIncompleteStatement(completeness));
833
830
 
@@ -846,7 +843,7 @@ export function runDoctor(root, config, files, rules, violations, asJson, option
846
843
  suggest:
847
844
  'thin or new tree; architecture config is not yet in charge. You do not pick this light. Next: ark start (preview), then ark start --apply; re-check with --doctor.',
848
845
  adapt:
849
- 'config and tree still disagree, or debt is open. The write path does not fully protect you yet. You do not pick this light. Next: do doctor top action #1 (often /ark-adopt, /ark-contract, or /ark-autopilot).',
846
+ 'config and tree still disagree, or debt is open. The write path does not fully protect you yet. You do not pick this light. Next: do doctor top action #1 (often /ark-adopt or /ark-autopilot).',
850
847
  enforce:
851
848
  'honest coverage and clean checked imports. You arrived here; you never turn Enforce on. Next: keep the host write path and CI check; only NEW violations should fail.',
852
849
  };
@@ -866,6 +863,63 @@ export function runDoctor(root, config, files, rules, violations, asJson, option
866
863
  );
867
864
  }
868
865
 
866
+ const safetyHasEntries = Boolean(
867
+ options.safety &&
868
+ [
869
+ options.safety.nonLiteralDynamicImports,
870
+ options.safety.tsSuppressions,
871
+ options.safety.anyCasts,
872
+ options.safety.inMemoryProductionStores,
873
+ options.safety.disabledPeerIsolationRules,
874
+ ].some((entries) => Array.isArray(entries) && entries.length > 0)
875
+ );
876
+ const uniqueActions = collectDoctorNextActions({
877
+ root,
878
+ analysisComplete,
879
+ designSmells,
880
+ postGreenPath,
881
+ coverageHonesty,
882
+ cov,
883
+ packageVersionTruth,
884
+ dualTruthNext,
885
+ activeCount,
886
+ writePath,
887
+ gatesMissing,
888
+ skillGaps,
889
+ codexHomeGap: detectCodexHomeGap(root),
890
+ codexConcernActive: codexConcernIsActive(),
891
+ agentHomeGaps,
892
+ baselineHonesty,
893
+ staleBaseline,
894
+ staleRunners,
895
+ adoption,
896
+ safety: options.safety,
897
+ safetyHasEntries,
898
+ showNewHere,
899
+ designFitness,
900
+ });
901
+ console.log('');
902
+ if (isDoctorHealthyNothingToDo(designFitness, uniqueActions)) {
903
+ console.log(color.green('✔ Healthy — nothing to do.'));
904
+ console.log(color.dim(' Contract edges and design residual are clear. Keep write path + CI.'));
905
+ } else {
906
+ console.log(color.bold('Primary next action'));
907
+ console.log(` 1. ${uniqueActions[0]}`);
908
+ if (uniqueActions.length > 1) {
909
+ console.log(color.bold(`Also (${uniqueActions.length - 1}):`));
910
+ uniqueActions.slice(1).forEach((action, index) => console.log(` ${index + 2}. ${action}`));
911
+ }
912
+ if (postGreenPath) {
913
+ console.log(
914
+ color.dim(
915
+ ` Shape residual is the primary door under ${modeTitle} — do not skill-shop explore vs coverage vs think.`
916
+ )
917
+ );
918
+ } else {
919
+ console.log(color.dim(' Doctor is the control plane: do #1 first, then re-run --doctor.'));
920
+ }
921
+ }
922
+
869
923
  // P0-B — single honesty surface (never a score; never "all good" when residual remains).
870
924
  if (productHonesty) {
871
925
  console.log('');
@@ -907,11 +961,7 @@ export function runDoctor(root, config, files, rules, violations, asJson, option
907
961
  line(' ', color.dim(`evidence: ${smell.evidence.slice(0, 4).join(', ')}`));
908
962
  }
909
963
  }
910
- if (postGreenPath) {
911
- // Rank first via mergePostGreenTopActions at the end (Q01 single door).
912
- actions.push(postGreenPath.action);
913
- }
914
- // Q04 — surface one next pilot under design-weak.
964
+ // Q04 — surface one next pilot under leftover design work.
915
965
  if (pilotLoop?.active && pilotLoop.nextPilot) {
916
966
  const np = pilotLoop.nextPilot;
917
967
  line(
@@ -967,13 +1017,9 @@ export function runDoctor(root, config, files, rules, violations, asJson, option
967
1017
  line(govMark, `Governed: ${cov.governed.percent}% (${cov.governed.classifiedFiles}/${cov.governed.totalFiles} files)`);
968
1018
  if (coverageHonesty.greenIsNotEnforcement) {
969
1019
  line(coverageHonesty.worseThanNoGate ? bad : warn, coverageHonesty.message);
970
- if (coverageHonesty.worseThanNoGate) {
971
- actions.push('raise governed coverage above a minority slice before treating green as enforcement');
972
- }
973
1020
  }
974
1021
  if (cov.suggestions.length > 0) {
975
1022
  line(warn, `${cov.suggestions.length} ungoverned director(y/ies) — proposals: ${arkCommand(root, 'ark-check', '--coverage')}`);
976
- actions.push('classify the ungoverned directories (/ark-contract)');
977
1023
  }
978
1024
  if (cov.emptyLayers.length > 0) line(warn, `Empty layers (pattern matches nothing): ${cov.emptyLayers.join(', ')}`);
979
1025
  if (cov.layersWithoutRules.length > 0) line(warn, `Layers with no rule edge: ${cov.layersWithoutRules.join(', ')}`);
@@ -989,18 +1035,10 @@ export function runDoctor(root, config, files, rules, violations, asJson, option
989
1035
  console.log('');
990
1036
  console.log(color.bold('Package pin (dual-truth)'));
991
1037
  line(warn, packageVersionTruth.note);
992
- actions.push(
993
- dualTruthNext ||
994
- 'bump package.json arkgate pin to match this CLI (or install without --no-install)'
995
- );
996
1038
  } else if (packageVersionTruth?.code === 'PACKAGE_PIN_ABSENT') {
997
1039
  console.log('');
998
1040
  console.log(color.bold('Package pin'));
999
1041
  line(warn, packageVersionTruth.note);
1000
- actions.push(
1001
- dualTruthNext ||
1002
- 'Add arkgate to package.json and install so CI/npx resolve this CLI (PACKAGE_PIN_ABSENT)'
1003
- );
1004
1042
  }
1005
1043
  if (options.configWalkedUp && options.configRoot) {
1006
1044
  line(
@@ -1030,7 +1068,6 @@ export function runDoctor(root, config, files, rules, violations, asJson, option
1030
1068
  line(warn, 'Low governed coverage or fresh config — finish start, then re-run doctor before adding layers of code.');
1031
1069
  }
1032
1070
  line(ok, `Optional sensor detail: ${arkCommand(root, 'ark-check', '--recommend')}`);
1033
- actions.unshift('finish ark start (preview + --apply), then re-run --doctor');
1034
1071
  }
1035
1072
 
1036
1073
  console.log('');
@@ -1058,11 +1095,6 @@ export function runDoctor(root, config, files, rules, violations, asJson, option
1058
1095
  if (summary.concentrated) {
1059
1096
  line(warn, color.dim(`${Math.round(summary.dominantShare * 100)}% on one edge (${summary.dominant}) — likely a contract fix, not debt`));
1060
1097
  }
1061
- if (activeCount > 0) {
1062
- actions.push(
1063
- `resolve the non-baselined violations — see the classified plan (${arkCommand(root, 'ark-check', '--plan')}), then /ark-fix`
1064
- );
1065
- }
1066
1098
  }
1067
1099
 
1068
1100
  console.log('');
@@ -1105,7 +1137,6 @@ export function runDoctor(root, config, files, rules, violations, asJson, option
1105
1137
  line(writePath.gap.severity === 'warn' ? warn : warn, writePath.gap.message);
1106
1138
  if (writePath.gap.fix) {
1107
1139
  line(' ', color.dim(`Fix: ${writePath.gap.fix}`));
1108
- actions.push(writePath.gap.fix);
1109
1140
  }
1110
1141
  }
1111
1142
 
@@ -1114,7 +1145,6 @@ export function runDoctor(root, config, files, rules, violations, asJson, option
1114
1145
  if (gatesMissing.length === 0) line(ok, 'Shared gate artifacts found on disk (AGENTS.md, .mcp.json, CI); runtime activation is reported separately');
1115
1146
  else {
1116
1147
  line(bad, `Missing gates: ${gatesMissing.join(', ')}`);
1117
- actions.push(`install gates (${arkCommand(root, 'ark-check', '--install-agent-gates')})`);
1118
1148
  }
1119
1149
  const humanSkillGaps = skillGapsForActiveHost(skillGaps);
1120
1150
  const legacyCodex = humanSkillGaps.some((g) => g.tool === 'codex' && g.legacyPromptsOnly);
@@ -1129,7 +1159,6 @@ export function runDoctor(root, config, files, rules, violations, asJson, option
1129
1159
  if (remMiss + remStale === 0 && !legacyCodex) line(ok, '/ark-* skills current for detected tools');
1130
1160
  if (legacyCodex) {
1131
1161
  line(warn, 'Codex: legacy flat .codex/prompts only (not a loadable skill catalog)');
1132
- actions.push('install Codex SKILL.md catalog (--install-agent-gates --skills-only --tools codex --force)');
1133
1162
  }
1134
1163
  if (codexLegacySafeDelete) {
1135
1164
  line(
@@ -1144,7 +1173,6 @@ export function runDoctor(root, config, files, rules, violations, asJson, option
1144
1173
  warn,
1145
1174
  `${remMiss} missing / ${remStale} content-behind-package /ark-* skill(s) for ${remainingGaps.map((g) => g.tool).join(', ')}`
1146
1175
  );
1147
- actions.push('refresh /ark-* skills (--install-agent-gates --skills-only --force)');
1148
1176
  }
1149
1177
  const codexHomeGap = detectCodexHomeGap(root);
1150
1178
  if (codexHomeGap) {
@@ -1159,7 +1187,6 @@ export function runDoctor(root, config, files, rules, violations, asJson, option
1159
1187
  line(color.dim('·'), color.dim(`Codex home skills ${parts.join(', ')} (deferred — not on Codex session)`));
1160
1188
  } else {
1161
1189
  line(warn, `Codex home skills ${parts.join(', ')}`);
1162
- actions.push(codexHomeGap.catalogMetadataInvalid ? 'repair invalid Codex home catalog metadata after verifying the newest installed version' : 'refresh Codex home skills (--install-agent-gates --skills-only --codex-home --force)');
1163
1190
  }
1164
1191
  }
1165
1192
  for (const gap of agentHomeGaps) {
@@ -1174,11 +1201,6 @@ export function runDoctor(root, config, files, rules, violations, asJson, option
1174
1201
  line(color.dim('·'), color.dim(`${summary} (deferred — not this session)`));
1175
1202
  } else {
1176
1203
  line(warn, summary);
1177
- actions.push(
1178
- gap.catalogMetadataInvalid
1179
- ? `repair invalid ${gap.label} home catalog metadata after verifying the newest installed version`
1180
- : `refresh ${gap.label} shared agent skills (${agentHomeRefreshCommand(root, gap)})`
1181
- );
1182
1204
  }
1183
1205
  }
1184
1206
 
@@ -1193,11 +1215,9 @@ export function runDoctor(root, config, files, rules, violations, asJson, option
1193
1215
  line(baseMark, `${baseline.keys.size} frozen key(s)${analysisComplete ? '' : ' — stale comparison not verified'}`);
1194
1216
  if (analysisComplete && baselineHonesty.dirtyBaselineRisk) {
1195
1217
  line(warn, baselineHonesty.message);
1196
- actions.push('review dirty baseline freezes — fix the contract before trusting green-via-freeze');
1197
1218
  }
1198
1219
  if (analysisComplete && staleBaseline > 0) {
1199
1220
  line(warn, `${staleBaseline} stale entr(y/ies) no longer occur — tighten with --update-baseline`);
1200
- actions.push('tighten the baseline (--update-baseline)');
1201
1221
  }
1202
1222
  }
1203
1223
 
@@ -1206,7 +1226,6 @@ export function runDoctor(root, config, files, rules, violations, asJson, option
1206
1226
  if (staleRunners.length === 0) line(ok, 'Emitted commands match the package manager');
1207
1227
  else {
1208
1228
  line(warn, `Stale runner in ${staleRunners.join(', ')}`);
1209
- actions.push(`migrate command runners (${arkCommand(root, 'ark-check', '--install-agent-gates --migrate-commands')})`);
1210
1229
  }
1211
1230
 
1212
1231
  // Adoption completeness (hosts, MCP health, codex home, core optionality, origin, baseline policy)
@@ -1232,7 +1251,6 @@ export function runDoctor(root, config, files, rules, violations, asJson, option
1232
1251
  if (gap.fix) {
1233
1252
  line(' ', color.dim(gap.deferred ? `When using Codex: ${gap.fix}` : `Fix: ${gap.fix}`));
1234
1253
  }
1235
- if (!gap.deferred) actions.push(gap.fix || gap.message);
1236
1254
  }
1237
1255
  if (adoption.layerBalance) {
1238
1256
  line(warn, color.dim(adoption.layerBalance.educational));
@@ -1269,34 +1287,6 @@ export function runDoctor(root, config, files, rules, violations, asJson, option
1269
1287
  for (const [label, entries] of rows) {
1270
1288
  line(entries.length === 0 ? ok : warn, `${label}: ${entries.length}`);
1271
1289
  }
1272
- if (rows.some(([, entries]) => entries.length > 0)) {
1273
- actions.push('resolve strict safety diagnostics before treating CI as enforcement');
1274
- }
1275
1290
  }
1276
1291
 
1277
- console.log('');
1278
- const uniqueActions = mergePostGreenTopActions(actions, postGreenPath);
1279
- if (isDoctorHealthyNothingToDo(designFitness, uniqueActions)) {
1280
- console.log(color.green('✔ Healthy — nothing to do.'));
1281
- console.log(color.dim(' Contract edges and design residual are clear. Keep write path + CI.'));
1282
- } else {
1283
- if (designFitness.designWeak && uniqueActions.length === 0 && postGreenPath) {
1284
- uniqueActions.push(postGreenPath.action);
1285
- }
1286
- console.log(color.bold(`Primary next action`));
1287
- console.log(` 1. ${uniqueActions[0]}`);
1288
- if (uniqueActions.length > 1) {
1289
- console.log(color.bold(`Also (${uniqueActions.length - 1}):`));
1290
- uniqueActions.slice(1).forEach((action, index) => console.log(` ${index + 2}. ${action}`));
1291
- }
1292
- if (postGreenPath) {
1293
- console.log(
1294
- color.dim(
1295
- ` Shape residual is the primary door under ${modeTitle} — do not skill-shop explore vs coverage vs think.`
1296
- )
1297
- );
1298
- } else {
1299
- console.log(color.dim(' Doctor is the control plane: do #1 first, then re-run --doctor.'));
1300
- }
1301
- }
1302
1292
  }
@@ -506,7 +506,7 @@ export function detectContractFalseGreenRisk(root, config, coverage) {
506
506
  `Contract may be a false green: empty core layer(s) [${emptyCores.join(', ')}] while ` +
507
507
  `Application-class globs still cover I/O paths (${ioPaths.slice(0, 5).join(', ')}` +
508
508
  `${ioPaths.length > 5 ? ', …' : ''}). A clean check can miss real coupling.`,
509
- fix: 'Run /ark-adopt or /ark-contract — reclassify persistence/auth dirs out of Application before claiming ENFORCE.',
509
+ fix: 'Run /ark-adopt — reclassify persistence/auth dirs out of Application before claiming ENFORCE.',
510
510
  };
511
511
  }
512
512
 
@@ -0,0 +1,221 @@
1
+ /**
2
+ * First-run CLI help (setup + check). Encyclopedia text stays behind --help --all.
3
+ */
4
+
5
+ export function setupUsage() {
6
+ return `arkgate (alias ark) — One architecture config. One check. One coach.
7
+
8
+ arkgate start preview what will change (no writes)
9
+ arkgate start --apply write the compact contract + host router + CI
10
+ arkgate-check --doctor status light + primary next action
11
+
12
+ Then session 0 in your agent: /ark-adopt
13
+ Stuck? Run doctor. Do #1.
14
+
15
+ More commands and flags: arkgate --help --all
16
+ `;
17
+ }
18
+
19
+ export function upgradeUsage() {
20
+ return `arkgate upgrade (alias ark upgrade) — preview vs apply.
21
+
22
+ arkgate upgrade preview managed updates (no writes)
23
+ arkgate upgrade --apply apply the previewed bytes (needs --plan-digest when applying managed files)
24
+
25
+ Customized files stay unless you pass --accept-conflicts or --refresh-skills.
26
+ Then: arkgate-check --doctor
27
+
28
+ Every flag: arkgate --help --all
29
+ `;
30
+ }
31
+
32
+ export function setupUsageAll() {
33
+ return `arkgate (alias ark) — One architecture config. One check. One coach.
34
+
35
+ Usage:
36
+ arkgate start [--root <project>] [--tools <host>] [--require-write-hook <host>] [--install] [--apply] [--json]
37
+ arkgate init [--root <project>] [--preset hexagonal|layered|feature-sliced|monorepo|ui-surface|vertical-slice|ddd-bounded-contexts|clean-architecture|onion-architecture]
38
+ [--archetype <playbook-id>] [--tools <list>] [--require-write-hook <host>] [--yes] [--force] [--no-strict]
39
+ arkgate upgrade [--root <project>] [--tools <list>] [--apply] [--plan-digest <sha256>] [--accept-conflicts] [--refresh-skills] [--json] [--no-install] [--no-strict]
40
+ arkgate preflight --changes <change-set.json> [--change-map <map.json>] [--root <project>] [--config ark.config.json] [--manifest <manifest.json>] [--tsconfig <tsconfig.json>] [--json]
41
+ arkgate status [--root <project>] [--config ark.config.json] [--json] [--vs <git-ref>]
42
+ [--expected-root <abs>] [--expected-project-id sha256:…] [--tools <host>]
43
+ arkgate agents-md [--root <project>] [--config ark.config.json] [--write] [--check] [--stdout] [--json]
44
+ [--tools <host>]
45
+
46
+ Commands:
47
+ start New here? Analyze and preview the complete setup. Read-only unless --apply.
48
+ init Configure Ark project enforcement with explicit prompts.
49
+ upgrade Preview identity-proven Ark-managed asset updates. With package install,
50
+ --apply bumps toward registry latest when behind (not only when CLI ≠ pin)
51
+ and recomputes the preview; a second explicit --apply --no-install applies
52
+ those exact bytes and verifies them. --refresh-skills opts in to rewrite
53
+ customized managed skills to package templates (never silent default).
54
+ (alias: ark update)
55
+ preflight Validate one atomic create/update/delete set without writing project files.
56
+ status Unified session/project manifest (identity, activation, last check, rules).
57
+ Never prompts. Prefer --json for agents; CI=1 forces JSON.
58
+ agents-md Version-matched agent contract projection (ACS04). Stamps package version +
59
+ contract summary into a managed AGENTS.md block. Non-authoritative — not a
60
+ gate input. Preview by default; --write merges without clobbering outside
61
+ regions; --check fails on version drift; --stdout prints the block only.
62
+ (aliases: agents-md, agent-projection)
63
+
64
+ Options:
65
+ --yes Non-interactive defaults: create config if needed, install gate templates, run strict check.
66
+ (Also the implicit default when stdin/stdout are not a TTY — agents never hang on prompts.)
67
+ --force Allow generated files to overwrite existing files.
68
+ --no-strict Skip the final strict ark-check run.
69
+ --install Pin and install arkgate as a project devDependency (default for start).
70
+ --no-install Skip adding/installing arkgate as a project devDependency (start/upgrade).
71
+ --apply Apply a start plan; for upgrade, update/repreview or apply managed bytes.
72
+ --accept-conflicts
73
+ Allow upgrade to recreate deleted managed assets or replace recorded conflicts.
74
+ --plan-digest Digest emitted by an upgrade preview; required to apply managed bytes.
75
+ --json Emit the start/upgrade/status/agents-md preview as deterministic machine-readable JSON.
76
+ --write For agents-md: merge the version-matched projection into AGENTS.md.
77
+ --check For agents-md: exit 1 when projection stamp drifts from package version.
78
+ --stdout For agents-md: print the projection block only (no file write).
79
+ --expected-root / --expected-project-id
80
+ Optional project expectation for status (MCP-compatible binding check).
81
+ --preset Start from a named architecture preset instead of detection.
82
+ --archetype Application shape from templates/architecture-playbook.json (maps to the matching preset).
83
+ Valid ids: crud-product, api-backend, frontend-surface, library-sdk, cli-utility,
84
+ worker-pipeline, event-coordinator, integration-bridge, multi-app-workspace, prototype-spike,
85
+ vertical-slice-product, ddd-bounded-contexts.
86
+ --tools One active agent host for start (claude,cursor,codex,grok,windsurf,cline,copilot,kiro,roo,continue,gemini).
87
+ Omit to use the active host; an unknown host creates only the shared compact router.
88
+ --remove-host <host>
89
+ Preview or apply removal of that compact host integration; re-add it with --tools <host>.
90
+ --require-write-hook <host>
91
+ Require and verify a hard local write hook for Claude, Grok, Antigravity, or Cursor.
92
+ Codex/OpenCode are advisory-write plus hard CI merge only; impossible requests fail before any write.
93
+
94
+ Interactive mode (TTY, no --yes): asks what application shape you are building and maps it to a preset.
95
+ Non-interactive (no TTY): uses the same defaults as --yes — never calls readline on a null interface.
96
+ `;
97
+ }
98
+
99
+ export function checkUsage() {
100
+ return [
101
+ 'arkgate-check (alias ark-check) — the architecture check.',
102
+ '',
103
+ ' arkgate-check --doctor where you are: one status light, one next action',
104
+ ' arkgate-check --strict-merge CI / merge gate (required GitHub status)',
105
+ '',
106
+ 'Every flag and command: arkgate-check --help --all',
107
+ ].join('\n');
108
+ }
109
+
110
+ export function checkUsageAll() {
111
+ return [
112
+ 'arkgate-check (alias ark-check) — the architecture check.',
113
+ '',
114
+ 'Usage: arkgate-check | ark-check (identical bins; product name ArkGate)',
115
+ ' arkgate-check --version',
116
+ ' arkgate-check --root <project> --config <ark.config.json> [--manifest <ark.manifest.json>] [--tsconfig <tsconfig.json>] [--strict-merge | --strict | --strict-config] [--policy-base <file> | --policy-base-ref <git-ref>] [--policy-ack <file>] [--fail-on-new-smells --base-ref <git-ref>] [--contract-diff] [--contract-session] [--changed] [--against <git-ref>] [--base <git-ref>] [--persona touch|contributor|agent|steward] [--author <id>] [--require-gates] [--require-write-hook <host>] [--json] [--baseline [file]] [--report [file.html]] [--no-cache]',
117
+ ' ark-check --doctor [--json] [--resident] [--fail-on-new-smells --base-ref <git-ref>] read-only diagnosis; resident JSON falls back cold',
118
+ ' ark-check --coverage [--json] per-layer file counts + full unclassified list (report only, exit 0)',
119
+ ' ark-check --plan [--json] classified remediation plan (mechanical-safe / judgment / deferred) + goal; report only',
120
+ ' ark-check --rules-inventory [--json] brownfield rules inventory (AR13; deterministic candidates, not a score)',
121
+ ' ark-check --recommend [--json] [--write-plan] application-shape plan; --write-plan emits ark-adoption-plan.json',
122
+ ' ark-check --list-policy-packs enthusiast packs (hexagonal, layered, feature-sliced, monorepo, ui-surface, vertical-slice, ddd-bounded-contexts)',
123
+ ' ark-check --apply-policy-pack <id> [--force] write ark.config.json from templates/policy-packs/ (uses preset factory)',
124
+ ' ark-check --suggest-include [--json] propose include roots (TS packages / workspaces)',
125
+ ' ark-check --adopt-contract [--write] expand include + layer patterns from ungoverned dirs (never bare lib→Presentation)',
126
+ ' ark-check --migrate-contract [--write] additive P0-A retrofit: inject app/api/** → Application when missing',
127
+ ' ark-check --ratchet-cores when raw graph is green (0 violations; baseline ignored), set optional:false on populated cores only (writes ark.config.json)',
128
+ ' ark-check --watch re-run the check when governed files change (debounced)',
129
+ ' ark-check --report [file.html] [--beginner] [--reset-origin] [--no-archive] [--open|--no-open]',
130
+ ' HTML report + snapshots under .ark/reports/ (origin once, latest each run, history JSON)',
131
+ ' Best-effort open in browser (local TTY). No-op if open fails. --no-open / ARK_NO_OPEN_REPORT=1 to skip; --open forces open.',
132
+ ' ark-check --init [--preset hexagonal|layered|feature-sliced|monorepo|ui-surface|vertical-slice|ddd-bounded-contexts|vite-vercel-spa|clean-architecture|onion-architecture] [--force] [--follow-config-root]',
133
+ ' --follow-config-root On writes (init/install-agent-gates/migrate --write/…), adopt walked-up monorepo config root (default: keep explicit --root)',
134
+ ' ark-check --install-agent-gates [--tools claude,cursor,codex,grok] [--require-write-hook <host>] [--skills-only] [--codex-home] [--claude-home] [--grok-home] [--agent-homes] [--force]',
135
+ ' ark-check --update-baseline [file] freeze current violations (default .ark-baseline.json)',
136
+ ' ark-check --print-config eleven-layer',
137
+ '',
138
+ 'Adopting Ark in an existing codebase? Run --update-baseline once to freeze existing',
139
+ 'violations, commit the baseline file, and gate CI with --baseline: only NEW violations',
140
+ 'fail the check, so the ratchet only moves toward zero.',
141
+ '',
142
+ 'Team parliament: law files (ark.config / arkrules / .ark-baseline.json) cannot ship in',
143
+ 'the same diff as product source. --changed --base <ref> checks touched files only.',
144
+ '--against <ref> ratchets new keys vs that ref\'s baseline. --contract-session is a',
145
+ 'steward law-only PR. Loosen / baseline-grow need stewards[] + --author when set.',
146
+ '',
147
+ '--init scans the project for the built-in layer directory conventions (src/domain,',
148
+ 'src/application, src/adapters/persistence, ...) and writes an ark.config.json covering',
149
+ 'only the layers that actually exist, with the default rules filtered to those layers.',
150
+ 'Undetected profile layers are printed as suggestions with their conventional',
151
+ 'directories. When nothing is detected, the full 11-layer starter profile is written',
152
+ 'instead (all layers optional, anchored at src/), so the strict check passes today and',
153
+ 'each layer starts being enforced as soon as its directory gains source files.',
154
+ '',
155
+ 'Resolves relative, tsconfig path-alias, and package imports via the TypeScript',
156
+ 'module resolver, then checks each resolved cross-layer import against the rules.',
157
+ 'Path aliases resolve against the NEAREST tsconfig.json above each source file, so',
158
+ 'monorepo packages with per-package configs work under a single --root. Pass',
159
+ '--tsconfig to force one config for every file. If no tsconfig is found, path',
160
+ 'aliases are unavailable but relative/package imports still resolve.',
161
+ '',
162
+ 'The correctness path resolves and parses one complete candidate on every invocation.',
163
+ 'Legacy node_modules/.cache/ark-check.json files are ignored. --no-cache remains an',
164
+ 'accepted compatibility no-op; the identity-keyed warm snapshot is introduced in Z07.',
165
+ '',
166
+ 'Config shape:',
167
+ '{',
168
+ ' "include": ["src"],',
169
+ ' // optional: "exclude": ["**/vendor/**"], "excludeGenerated": false (default skips *.gen.ts / *.generated.ts)',
170
+ ' "layers": [',
171
+ ' { "name": "DomainModel", "patterns": ["src/domain/**"], "intentPrefixes": ["Domain."],',
172
+ ' "forbiddenGlobals": ["fetch", "process", "Date.now", "Math.random"] }',
173
+ ' ],',
174
+ ' "rules": [{ "from": "DomainModel", "to": "PersistenceAdapters", "allowed": false }]',
175
+ '}',
176
+ '',
177
+ 'Config warnings are advisory by default and are included in JSON output.',
178
+ 'Use --strict-config to make config warnings fail the check.',
179
+ 'Use --strict-merge for the fail-closed CI profile: --strict-config + --require-gates',
180
+ 'plus the security diagnostics surfaced by doctor. --strict is a compatibility alias.',
181
+ 'This merge profile never depends on an editor/agent hook.',
182
+ 'When a Git merge base is available, --strict-merge classifies the ark.config.json',
183
+ 'transition. Weakening or judgment-required findings fail unless --policy-ack names',
184
+ 'every finding and is bound to both policy hashes. Use --policy-base/--policy-base-ref',
185
+ 'for an explicit comparison; ARK_POLICY_BASE_REF is the CI environment equivalent.',
186
+ 'Add --require-write-hook claude|grok|antigravity|cursor to validate a hard local write',
187
+ 'boundary for that specific host. Codex and OpenCode expose advisory MCP (plus best-effort',
188
+ 'hooks where applicable) and the shared CI check; merge blocking requires repository policy',
189
+ 'to make that status required.',
190
+ '',
191
+ '--require-gates implies --strict-config and fails when the Ark contract in AGENTS.md,',
192
+ 'the project-rooted Ark server in .mcp.json, or fail-closed CI is missing/invalid.',
193
+ 'Included but unclassified source files therefore stay red instead of false-green.',
194
+ '',
195
+ '--install-agent-gates writes AGENTS.md, .mcp.json, and the CI workflow for every',
196
+ 'project, plus tool-specific templates. Known tools: claude, cursor, codex, grok',
197
+ '(Claude/Grok/Antigravity/Cursor hard-write hooks when covered; Codex advisory MCP;',
198
+ 'shared CI check for all) and',
199
+ 'windsurf, cline, copilot, kiro, roo, continue, gemini',
200
+ '(instruction-tier rule files derived from the same contract).',
201
+ 'It also installs the /ark-* skills shipped in templates/skills/ into each',
202
+ 'detected tool\'s command location (.claude/skills/, .cursor/commands/,',
203
+ '.agents/skills/ (Codex REPO catalog), .grok/skills/, .windsurf/workflows/,',
204
+ '.clinerules/workflows/, .github/prompts/).',
205
+ 'Kiro, Roo, Continue, and Gemini have no command mechanism and receive only their',
206
+ 'rule file. Existing files are never overwritten without --force, so re-running',
207
+ 'after an update only adds what is missing. --skills-only restricts the write to',
208
+ 'just the /ark-* skills (safe to --force-refresh — it leaves a customized AGENTS.md,',
209
+ 'settings, and CI workflow untouched).',
210
+ 'Pass --tools to pick which tool configs to write; otherwise they are auto-detected',
211
+ 'from their config directories (.claude/, .cursor/, .codex/, .grok/, .windsurf/,',
212
+ '.clinerules/, .kiro/, .roo/, .continue/, .gemini/; copilot is explicit-only).',
213
+ 'claude+cursor+codex+grok are written when nothing is detected.',
214
+ '',
215
+ 'Generate a starter 11-layer config:',
216
+ ' ark-check --print-config eleven-layer > ark.config.json',
217
+ '',
218
+ 'Install agent + CI enforcement templates:',
219
+ ' ark-check --install-agent-gates',
220
+ ].join('\n');
221
+ }