pumuki 6.3.97 → 6.3.99

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 (96) hide show
  1. package/AGENTS.md +269 -0
  2. package/CHANGELOG.md +697 -0
  3. package/README.md +4 -2
  4. package/VERSION +1 -1
  5. package/docs/README.md +13 -9
  6. package/docs/operations/RELEASE_NOTES.md +12 -76
  7. package/docs/product/HOW_IT_WORKS.md +6 -0
  8. package/docs/product/INSTALLATION.md +1 -1
  9. package/docs/product/USAGE.md +41 -4
  10. package/docs/tracking/plan-curso-pumuki-stack-my-architecture.md +118 -0
  11. package/docs/validation/README.md +6 -3
  12. package/integrations/config/skillsCustomRules.ts +18 -99
  13. package/integrations/evidence/buildEvidence.ts +0 -24
  14. package/integrations/evidence/repoState.ts +0 -3
  15. package/integrations/evidence/schema.ts +0 -18
  16. package/integrations/evidence/writeEvidence.ts +0 -24
  17. package/integrations/gate/evaluateAiGate.ts +15 -232
  18. package/integrations/gate/remediationCatalog.ts +0 -8
  19. package/integrations/git/GitService.ts +44 -5
  20. package/integrations/git/aiGateRepoPolicyFindings.ts +0 -4
  21. package/integrations/git/runPlatformGate.ts +1 -9
  22. package/integrations/git/runPlatformGateFacts.ts +19 -1
  23. package/integrations/git/runPlatformGateOutput.ts +27 -36
  24. package/integrations/lifecycle/adapter.templates.json +7 -13
  25. package/integrations/lifecycle/adapter.ts +0 -24
  26. package/integrations/lifecycle/artifacts.ts +1 -6
  27. package/integrations/lifecycle/audit.ts +101 -0
  28. package/integrations/lifecycle/cli.ts +110 -70
  29. package/integrations/lifecycle/cliSdd.ts +13 -8
  30. package/integrations/lifecycle/doctor.ts +16 -48
  31. package/integrations/lifecycle/hookManager.ts +0 -77
  32. package/integrations/lifecycle/index.ts +2 -0
  33. package/integrations/lifecycle/install.ts +0 -21
  34. package/integrations/lifecycle/npmService.ts +3 -155
  35. package/integrations/lifecycle/policyValidationSnapshot.ts +8 -2
  36. package/integrations/lifecycle/preWriteAutomation.ts +7 -77
  37. package/integrations/lifecycle/state.ts +1 -8
  38. package/integrations/lifecycle/status.ts +2 -29
  39. package/integrations/mcp/aiGateCheck.ts +26 -206
  40. package/integrations/mcp/autoExecuteAiStart.ts +87 -94
  41. package/integrations/mcp/enterpriseServer.ts +7 -23
  42. package/integrations/mcp/enterpriseStdioServer.cli.ts +4 -31
  43. package/integrations/mcp/preFlightCheck.ts +5 -51
  44. package/integrations/platform/detectPlatforms.ts +37 -0
  45. package/integrations/policy/experimentalFeatures.ts +1 -1
  46. package/integrations/sdd/evidenceScaffold.ts +2 -109
  47. package/package.json +10 -2
  48. package/scripts/check-tracking-single-active.sh +1 -1
  49. package/scripts/consumer-menu-matrix-baseline-report-lib.ts +13 -38
  50. package/scripts/consumer-postinstall-resolve-args.cjs +44 -0
  51. package/scripts/consumer-postinstall.cjs +76 -21
  52. package/scripts/framework-menu-advanced-view-lib.ts +0 -15
  53. package/scripts/framework-menu-consumer-actions-lib.ts +28 -4
  54. package/scripts/framework-menu-consumer-preflight-hints.ts +5 -2
  55. package/scripts/framework-menu-consumer-preflight-render.ts +0 -10
  56. package/scripts/framework-menu-consumer-preflight-run.ts +0 -23
  57. package/scripts/framework-menu-consumer-preflight-types.ts +0 -12
  58. package/scripts/framework-menu-consumer-runtime-actions.ts +87 -17
  59. package/scripts/framework-menu-consumer-runtime-audit.ts +36 -2
  60. package/scripts/framework-menu-consumer-runtime-evidence-classic.ts +140 -0
  61. package/scripts/framework-menu-consumer-runtime-lib.ts +2 -10
  62. package/scripts/framework-menu-consumer-runtime-menu.ts +4 -18
  63. package/scripts/framework-menu-consumer-runtime-types.ts +3 -3
  64. package/scripts/framework-menu-evidence-summary-lib.ts +1 -0
  65. package/scripts/framework-menu-evidence-summary-read.ts +57 -5
  66. package/scripts/framework-menu-evidence-summary-severity.ts +3 -1
  67. package/scripts/framework-menu-evidence-summary-types.ts +7 -0
  68. package/scripts/framework-menu-gate-lib.ts +9 -0
  69. package/scripts/framework-menu-layout-data.ts +5 -0
  70. package/scripts/framework-menu-matrix-baseline-lib.ts +15 -14
  71. package/scripts/framework-menu-matrix-canary-lib.ts +22 -1
  72. package/scripts/framework-menu-matrix-evidence-lib.ts +1 -0
  73. package/scripts/framework-menu-matrix-evidence-types.ts +13 -1
  74. package/scripts/framework-menu-matrix-runner-lib.ts +35 -0
  75. package/scripts/framework-menu-system-notifications-cause.ts +0 -24
  76. package/scripts/framework-menu-system-notifications-macos-swift-source.ts +24 -204
  77. package/scripts/framework-menu-system-notifications-macos.ts +4 -0
  78. package/scripts/framework-menu-system-notifications-payloads-blocked.ts +1 -1
  79. package/scripts/framework-menu-system-notifications-remediation.ts +13 -24
  80. package/scripts/framework-menu-system-notifications-text.ts +1 -7
  81. package/scripts/framework-menu.ts +3 -2
  82. package/scripts/package-install-smoke-consumer-git-repo-lib.ts +1 -10
  83. package/scripts/package-install-smoke-consumer-npm-lib.ts +9 -46
  84. package/scripts/pumuki-full-surface-smoke-lib.ts +37 -0
  85. package/scripts/pumuki-full-surface-smoke.ts +346 -0
  86. package/scripts/pumuki-smoke-installed-wrapper.cjs +31 -0
  87. package/integrations/evidence/trackingContract.ts +0 -150
  88. package/integrations/gate/governanceActionCatalog.ts +0 -275
  89. package/integrations/lifecycle/bootstrapManifest.ts +0 -248
  90. package/integrations/lifecycle/cliGovernanceConsole.ts +0 -69
  91. package/integrations/lifecycle/governanceNextAction.ts +0 -164
  92. package/integrations/lifecycle/governanceObservationSnapshot.ts +0 -613
  93. package/integrations/mcp/alignedPlatformGate.ts +0 -232
  94. package/integrations/mcp/readMcpPrePushStdin.ts +0 -7
  95. package/scripts/build-ruralgo-s1-evidence-pack.ts +0 -85
  96. package/scripts/ruralgo-s1-evidence-pack-lib.ts +0 -200
@@ -4,15 +4,11 @@ import type { GatePolicy } from '../../core/gate/GatePolicy';
4
4
  import { runPlatformGate } from '../git/runPlatformGate';
5
5
  import { collectWorktreeAtomicSlices } from '../git/worktreeAtomicSlices';
6
6
  import {
7
- doctorCommandShouldFailExit,
8
- doctorCommandShouldWarnHuman,
9
7
  doctorHasBlockingIssues,
10
- doctorHasGovernanceAttention,
11
8
  doctorHasParityMismatch,
12
9
  runLifecycleDoctor,
13
10
  type LifecycleDoctorReport,
14
11
  } from './doctor';
15
- import { printGovernanceConsoleHuman } from './cliGovernanceConsole';
16
12
  import { runLifecycleInstall } from './install';
17
13
  import { runLifecycleRemove } from './remove';
18
14
  import { readLifecycleStatus } from './status';
@@ -76,6 +72,7 @@ import {
76
72
  type RemoteCiDiagnostics,
77
73
  } from './remoteCiDiagnostics';
78
74
  import { runPolicyReconcile } from './policyReconcile';
75
+ import { runLifecycleAudit, type LifecycleAuditStage } from './audit';
79
76
  import { resolvePreWriteEnforcement, type PreWriteEnforcementResolution } from '../policy/preWriteEnforcement';
80
77
 
81
78
  type LifecycleCommand =
@@ -91,7 +88,8 @@ type LifecycleCommand =
91
88
  | 'sdd'
92
89
  | 'adapter'
93
90
  | 'analytics'
94
- | 'policy';
91
+ | 'policy'
92
+ | 'audit';
95
93
 
96
94
  type SddCommand =
97
95
  | 'status'
@@ -152,7 +150,6 @@ export type ParsedArgs = {
152
150
  sddEvidenceTestStatus?: SddEvidenceScaffoldTestStatus;
153
151
  sddEvidenceTestOutput?: string;
154
152
  sddEvidenceFromEvidence?: string;
155
- sddEvidenceTraceabilityMarkdown?: string;
156
153
  sddStateSyncDryRun?: boolean;
157
154
  sddStateSyncScenarioId?: string;
158
155
  sddStateSyncStatus?: SddStateSyncStatus;
@@ -178,6 +175,8 @@ export type ParsedArgs = {
178
175
  policyCommand?: PolicyCommand;
179
176
  policyStrict?: boolean;
180
177
  policyApply?: boolean;
178
+ auditStage?: LifecycleAuditStage;
179
+ auditEngine?: boolean;
181
180
  };
182
181
 
183
182
  const HELP_TEXT = `
@@ -188,6 +187,7 @@ Pumuki lifecycle commands:
188
187
  pumuki remove
189
188
  pumuki update [--latest|--spec=<package-spec>]
190
189
  pumuki doctor [--remote-checks] [--deep] [--parity] [--json]
190
+ pumuki audit [--stage=PRE_COMMIT|PRE_PUSH|CI] [--engine] [--json]
191
191
  pumuki status [--json] [--remote-checks]
192
192
  pumuki watch [--stage=PRE_COMMIT|PRE_PUSH|CI] [--scope=workingTree|staged|repoAndStaged|repo] [--severity=critical|high|medium|low] [--interval-ms=<n>] [--notify-cooldown-ms=<n>] [--no-notify] [--once|--iterations=<n>] [--json]
193
193
  pumuki loop run --objective=<text> [--max-attempts=<n>] [--json]
@@ -209,7 +209,7 @@ Pumuki lifecycle commands:
209
209
  pumuki sdd sync [--change=<change-id>] [--stage=PRE_WRITE|PRE_COMMIT|PRE_PUSH|CI] [--task=<task-id>] [--from-evidence=<path>] [--dry-run] [--json]
210
210
  pumuki sdd learn --change=<change-id> [--stage=PRE_WRITE|PRE_COMMIT|PRE_PUSH|CI] [--task=<task-id>] [--from-evidence=<path>] [--dry-run] [--json]
211
211
  pumuki sdd auto-sync --change=<change-id> [--stage=PRE_WRITE|PRE_COMMIT|PRE_PUSH|CI] [--task=<task-id>] [--from-evidence=<path>] [--dry-run] [--json]
212
- pumuki sdd evidence --scenario-id=<id> --test-command=<command> --test-status=passed|failed [--test-output=<path>] [--from-evidence=<path>] [--traceability-markdown=<path>] [--dry-run] [--json]
212
+ pumuki sdd evidence --scenario-id=<id> --test-command=<command> --test-status=passed|failed [--test-output=<path>] [--from-evidence=<path>] [--dry-run] [--json]
213
213
  pumuki sdd state-sync [--scenario-id=<id>] [--status=todo|in_progress|blocked|done] [--from-evidence=<path>] [--board-path=<path>] [--force] [--dry-run] [--json]
214
214
  aliases de --stage: RED=PRE_WRITE, GREEN=PRE_COMMIT, REFACTOR=PRE_PUSH, CLOSE=CI
215
215
  `.trim();
@@ -233,7 +233,8 @@ const isLifecycleCommand = (value: string): value is LifecycleCommand =>
233
233
  value === 'sdd' ||
234
234
  value === 'adapter' ||
235
235
  value === 'analytics' ||
236
- value === 'policy';
236
+ value === 'policy' ||
237
+ value === 'audit';
237
238
 
238
239
  const parseAdapterAgent = (value?: string): AdapterAgent => {
239
240
  const normalized = (value ?? '').trim();
@@ -263,6 +264,16 @@ const parseSddStage = (value?: string): SddStage => {
263
264
  throw new Error(`Unsupported SDD stage "${value}". Use PRE_WRITE, PRE_COMMIT, PRE_PUSH or CI.`);
264
265
  };
265
266
 
267
+ const parseAuditStage = (value?: string): LifecycleAuditStage => {
268
+ const stage = parseSddStage(value);
269
+ if (stage === 'PRE_WRITE') {
270
+ throw new Error(
271
+ 'PRE_WRITE is not supported for "pumuki audit". Use PRE_COMMIT, PRE_PUSH or CI (aliases GREEN, REFACTOR, CLOSE).'
272
+ );
273
+ }
274
+ return stage;
275
+ };
276
+
266
277
  const parseSddEvidencePath = (value: string): string => {
267
278
  const normalized = value.trim();
268
279
  if (normalized.length === 0) {
@@ -613,7 +624,6 @@ export const parseLifecycleCliArgs = (argv: ReadonlyArray<string>): ParsedArgs =
613
624
  let sddEvidenceTestStatus: ParsedArgs['sddEvidenceTestStatus'];
614
625
  let sddEvidenceTestOutput: ParsedArgs['sddEvidenceTestOutput'];
615
626
  let sddEvidenceFromEvidence: ParsedArgs['sddEvidenceFromEvidence'];
616
- let sddEvidenceTraceabilityMarkdown: ParsedArgs['sddEvidenceTraceabilityMarkdown'];
617
627
  let sddStateSyncDryRun = false;
618
628
  let sddStateSyncScenarioId: ParsedArgs['sddStateSyncScenarioId'];
619
629
  let sddStateSyncStatus: ParsedArgs['sddStateSyncStatus'];
@@ -629,6 +639,8 @@ export const parseLifecycleCliArgs = (argv: ReadonlyArray<string>): ParsedArgs =
629
639
  let analyticsSinceDays: ParsedArgs['analyticsSinceDays'];
630
640
  let analyticsJsonOutputPath: ParsedArgs['analyticsJsonOutputPath'];
631
641
  let analyticsMarkdownOutputPath: ParsedArgs['analyticsMarkdownOutputPath'];
642
+ let auditStage: LifecycleAuditStage | undefined;
643
+ let auditEngine = false;
632
644
 
633
645
  if (commandRaw === 'watch') {
634
646
  for (const arg of argv.slice(1)) {
@@ -812,6 +824,31 @@ export const parseLifecycleCliArgs = (argv: ReadonlyArray<string>): ParsedArgs =
812
824
  };
813
825
  }
814
826
 
827
+ if (commandRaw === 'audit') {
828
+ for (const arg of argv.slice(1)) {
829
+ if (arg === '--json') {
830
+ json = true;
831
+ continue;
832
+ }
833
+ if (arg === '--engine') {
834
+ auditEngine = true;
835
+ continue;
836
+ }
837
+ if (arg.startsWith('--stage=')) {
838
+ auditStage = parseAuditStage(arg.slice('--stage='.length));
839
+ continue;
840
+ }
841
+ throw new Error(`Unsupported argument "${arg}".\n\n${HELP_TEXT}`);
842
+ }
843
+ return {
844
+ command: commandRaw,
845
+ purgeArtifacts: false,
846
+ json,
847
+ auditStage: auditStage ?? 'PRE_COMMIT',
848
+ ...(auditEngine ? { auditEngine: true } : {}),
849
+ };
850
+ }
851
+
815
852
  if (commandRaw === 'loop') {
816
853
  const subcommandRaw = argv[1] ?? '';
817
854
  if (
@@ -1097,17 +1134,6 @@ export const parseLifecycleCliArgs = (argv: ReadonlyArray<string>): ParsedArgs =
1097
1134
  sddEvidenceTestOutput = testOutputPath;
1098
1135
  continue;
1099
1136
  }
1100
- if (arg.startsWith('--traceability-markdown=')) {
1101
- if (sddCommand !== 'evidence') {
1102
- throw new Error(`--traceability-markdown is only supported with "pumuki sdd evidence".\n\n${HELP_TEXT}`);
1103
- }
1104
- const traceabilityMarkdownPath = arg.slice('--traceability-markdown='.length).trim();
1105
- if (traceabilityMarkdownPath.length === 0) {
1106
- throw new Error(`Invalid --traceability-markdown value "${arg}".`);
1107
- }
1108
- sddEvidenceTraceabilityMarkdown = traceabilityMarkdownPath;
1109
- continue;
1110
- }
1111
1137
  if (arg.startsWith('--from-evidence=')) {
1112
1138
  if (sddCommand === 'sync-docs') {
1113
1139
  sddSyncDocsFromEvidence = parseSddEvidencePath(
@@ -1268,7 +1294,7 @@ export const parseLifecycleCliArgs = (argv: ReadonlyArray<string>): ParsedArgs =
1268
1294
  sddAutoSyncChange
1269
1295
  ) {
1270
1296
  throw new Error(
1271
- `"pumuki sdd evidence" only supports --scenario-id=<id> --test-command=<command> --test-status=passed|failed [--test-output=<path>] [--from-evidence=<path>] [--traceability-markdown=<path>] [--dry-run] [--json].\n\n${HELP_TEXT}`
1297
+ `"pumuki sdd evidence" only supports --scenario-id=<id> --test-command=<command> --test-status=passed|failed [--test-output=<path>] [--from-evidence=<path>] [--dry-run] [--json].\n\n${HELP_TEXT}`
1272
1298
  );
1273
1299
  }
1274
1300
  if (!sddEvidenceScenarioId) {
@@ -1291,7 +1317,6 @@ export const parseLifecycleCliArgs = (argv: ReadonlyArray<string>): ParsedArgs =
1291
1317
  sddEvidenceTestStatus,
1292
1318
  ...(sddEvidenceTestOutput ? { sddEvidenceTestOutput } : {}),
1293
1319
  ...(sddEvidenceFromEvidence ? { sddEvidenceFromEvidence } : {}),
1294
- ...(sddEvidenceTraceabilityMarkdown ? { sddEvidenceTraceabilityMarkdown } : {}),
1295
1320
  };
1296
1321
  }
1297
1322
  if (sddCommand === 'state-sync') {
@@ -1535,12 +1560,11 @@ const printDoctorReport = (
1535
1560
  writeInfo(
1536
1561
  `[pumuki] hook pre-push: ${report.hookStatus['pre-push'].managedBlockPresent ? 'managed' : 'missing'}`
1537
1562
  );
1538
- printGovernanceConsoleHuman({
1539
- governanceObservation: report.governanceObservation,
1540
- governanceNextAction: report.governanceNextAction,
1541
- policyValidation: report.policyValidation,
1542
- experimentalFeatures: report.experimentalFeatures,
1543
- });
1563
+ writeInfo(
1564
+ `[pumuki] policy-as-code: PRE_COMMIT=${report.policyValidation.stages.PRE_COMMIT.validationCode ?? 'n/a'} strict=${report.policyValidation.stages.PRE_COMMIT.strict ? 'yes' : 'no'} ` +
1565
+ `PRE_PUSH=${report.policyValidation.stages.PRE_PUSH.validationCode ?? 'n/a'} strict=${report.policyValidation.stages.PRE_PUSH.strict ? 'yes' : 'no'} ` +
1566
+ `CI=${report.policyValidation.stages.CI.validationCode ?? 'n/a'} strict=${report.policyValidation.stages.CI.strict ? 'yes' : 'no'}`
1567
+ );
1544
1568
 
1545
1569
  for (const issue of report.issues) {
1546
1570
  writeInfo(`[pumuki] ${issue.severity.toUpperCase()}: ${issue.message}`);
@@ -1573,19 +1597,17 @@ const printDoctorReport = (
1573
1597
  }
1574
1598
  }
1575
1599
 
1576
- const hasBlocking = doctorCommandShouldFailExit(report);
1577
- const hasWarnings = doctorCommandShouldWarnHuman(report);
1600
+ const hasBlocking =
1601
+ doctorHasBlockingIssues(report) || doctorHasParityMismatch(report);
1602
+ const hasWarnings =
1603
+ report.issues.length > 0 ||
1604
+ report.deep?.checks.some((check) => check.status !== 'pass') === true;
1578
1605
 
1579
1606
  if (!hasWarnings && !hasBlocking) {
1580
1607
  writeInfo('[pumuki] doctor verdict: PASS');
1581
1608
  } else {
1582
1609
  writeInfo(`[pumuki] doctor verdict: ${hasBlocking ? 'BLOCKED' : 'WARN'}`);
1583
1610
  }
1584
- if (!hasBlocking && doctorHasGovernanceAttention(report)) {
1585
- writeInfo(
1586
- '[pumuki] doctor: governance_effective is not GREEN (see governance truth).'
1587
- );
1588
- }
1589
1611
 
1590
1612
  if (remoteCiDiagnostics) {
1591
1613
  printRemoteCiDiagnostics(remoteCiDiagnostics);
@@ -1631,8 +1653,8 @@ export type PreWriteOpenSpecBootstrapTrace = {
1631
1653
  details?: string;
1632
1654
  };
1633
1655
 
1634
- export const PRE_WRITE_ENABLE_STRICT_COMMAND =
1635
- 'PUMUKI_EXPERIMENTAL_PRE_WRITE=strict npx --yes --package pumuki@latest pumuki sdd validate --stage=PRE_WRITE --json';
1656
+ export const PRE_WRITE_ENABLE_ADVISORY_COMMAND =
1657
+ 'PUMUKI_EXPERIMENTAL_PRE_WRITE=advisory npx --yes --package pumuki@latest pumuki sdd validate --stage=PRE_WRITE --json';
1636
1658
  export const buildSddExperimentalEnableAdvisoryCommand = (stage: SddStage): string =>
1637
1659
  `PUMUKI_EXPERIMENTAL_SDD=advisory npx --yes --package pumuki@latest pumuki sdd validate --stage=${stage} --json`;
1638
1660
  const buildAnalyticsExperimentalEnableCommand = (action: AnalyticsHotspotsCommand): string =>
@@ -1726,7 +1748,6 @@ const buildSaasIngestionExperimentalDisabledEnvelope = (
1726
1748
  export const buildPreWriteExperimentalDisabledResult = (params: {
1727
1749
  stage: SddStage;
1728
1750
  status: SddEvaluateResult['status'];
1729
- source: 'env' | 'legacy-env' | 'default';
1730
1751
  }): SddEvaluateResult => ({
1731
1752
  stage: params.stage,
1732
1753
  status: params.status,
@@ -1734,16 +1755,14 @@ export const buildPreWriteExperimentalDisabledResult = (params: {
1734
1755
  allowed: true,
1735
1756
  code: 'PRE_WRITE_EXPERIMENTAL_DISABLED',
1736
1757
  message:
1737
- 'PRE_WRITE está desactivado explícitamente. Reactívalo con PUMUKI_EXPERIMENTAL_PRE_WRITE=strict si necesitas recuperar el gate previo a escritura.',
1758
+ 'PRE_WRITE pertenece al namespace experimental y está desactivado por defecto. Actívalo explícitamente con PUMUKI_EXPERIMENTAL_PRE_WRITE=advisory o strict si necesitas este flujo.',
1738
1759
  details: {
1739
1760
  experimental: true,
1740
- default_off: false,
1741
- disabled_explicitly: true,
1742
- disabled_source: params.source,
1761
+ default_off: true,
1743
1762
  layer: 'experimental',
1744
1763
  activation_env: 'PUMUKI_EXPERIMENTAL_PRE_WRITE',
1745
1764
  legacy_activation_env: 'PUMUKI_PREWRITE_ENFORCEMENT',
1746
- activation_command: PRE_WRITE_ENABLE_STRICT_COMMAND,
1765
+ activation_command: PRE_WRITE_ENABLE_ADVISORY_COMMAND,
1747
1766
  },
1748
1767
  },
1749
1768
  });
@@ -2125,10 +2144,6 @@ export const runLifecycleCli = async (
2125
2144
  repo_root: installResult.repoRoot,
2126
2145
  version: installResult.version,
2127
2146
  hooks_changed: installResult.changedHooks,
2128
- bootstrap_manifest: {
2129
- path: installResult.bootstrapManifest.path,
2130
- changed: installResult.bootstrapManifest.changed,
2131
- },
2132
2147
  openspec: installResult.openSpecBootstrap
2133
2148
  ? {
2134
2149
  installed: installResult.openSpecBootstrap.packageInstalled,
@@ -2141,10 +2156,6 @@ export const runLifecycleCli = async (
2141
2156
  mcp: {
2142
2157
  agent: adapterResult.agent,
2143
2158
  changed_files: adapterResult.changedFiles,
2144
- bootstrap_manifest: {
2145
- path: adapterResult.bootstrapManifest.path,
2146
- changed: adapterResult.bootstrapManifest.changed,
2147
- },
2148
2159
  adapter_health: adapterCheck
2149
2160
  ? {
2150
2161
  status: adapterCheck.status,
@@ -2171,9 +2182,6 @@ export const runLifecycleCli = async (
2171
2182
  writeInfo(
2172
2183
  `[pumuki] bootstrap install: hooks changed=${installResult.changedHooks.join(', ') || 'none'}`
2173
2184
  );
2174
- writeInfo(
2175
- `[pumuki] bootstrap manifest: path=${installResult.bootstrapManifest.path} changed=${installResult.bootstrapManifest.changed ? 'yes' : 'no'}`
2176
- );
2177
2185
  if (installResult.openSpecBootstrap) {
2178
2186
  writeInfo(
2179
2187
  `[pumuki] bootstrap openspec: installed=${installResult.openSpecBootstrap.packageInstalled ? 'yes' : 'no'} project=${installResult.openSpecBootstrap.projectInitialized ? 'yes' : 'no'} actions=${installResult.openSpecBootstrap.actions.join(', ') || 'none'}`
@@ -2214,9 +2222,6 @@ export const runLifecycleCli = async (
2214
2222
  writeInfo(
2215
2223
  `[pumuki] installed ${result.version} at ${result.repoRoot} (hooks changed: ${result.changedHooks.join(', ') || 'none'})`
2216
2224
  );
2217
- writeInfo(
2218
- `[pumuki] bootstrap manifest: path=${result.bootstrapManifest.path} changed=${result.bootstrapManifest.changed ? 'yes' : 'no'}`
2219
- );
2220
2225
  if (result.openSpecBootstrap) {
2221
2226
  writeInfo(
2222
2227
  `[pumuki] openspec bootstrap: installed=${result.openSpecBootstrap.packageInstalled ? 'yes' : 'no'} project=${result.openSpecBootstrap.projectInitialized ? 'yes' : 'no'} actions=${result.openSpecBootstrap.actions.join(', ') || 'none'}`
@@ -2232,9 +2237,6 @@ export const runLifecycleCli = async (
2232
2237
  writeInfo(
2233
2238
  `[pumuki] mcp wiring: agent=${adapterResult.agent} changed=${adapterResult.changedFiles.length}`
2234
2239
  );
2235
- writeInfo(
2236
- `[pumuki] mcp manifest: path=${adapterResult.bootstrapManifest.path} changed=${adapterResult.bootstrapManifest.changed ? 'yes' : 'no'}`
2237
- );
2238
2240
  if (adapterResult.changedFiles.length > 0) {
2239
2241
  writeInfo(`[pumuki] mcp files: ${adapterResult.changedFiles.join(', ')}`);
2240
2242
  }
@@ -2291,6 +2293,24 @@ export const runLifecycleCli = async (
2291
2293
  );
2292
2294
  return 0;
2293
2295
  }
2296
+ case 'audit': {
2297
+ const result = await runLifecycleAudit({
2298
+ stage: parsed.auditStage ?? 'PRE_COMMIT',
2299
+ auditMode: parsed.auditEngine === true ? 'engine' : 'gate',
2300
+ });
2301
+ if (parsed.json) {
2302
+ writeInfo(JSON.stringify(result, null, 2));
2303
+ } else {
2304
+ writeInfo(
2305
+ `[pumuki] audit: repo=${result.repo_root} stage=${result.stage} mode=${result.audit_mode} exit=${result.gate_exit_code}`
2306
+ );
2307
+ writeInfo(
2308
+ `[pumuki] audit: files_scanned=${result.files_scanned ?? 'n/a'} untracked_matching_extensions=${result.untracked_matching_extensions_count} outcome=${result.snapshot_outcome ?? 'n/a'}`
2309
+ );
2310
+ writeInfo(`[pumuki] audit: hint=${result.policy_reconcile_hint}`);
2311
+ }
2312
+ return result.gate_exit_code;
2313
+ }
2294
2314
  case 'doctor': {
2295
2315
  const report = runLifecycleDoctor({
2296
2316
  deep: parsed.doctorDeep === true,
@@ -2317,7 +2337,7 @@ export const runLifecycleCli = async (
2317
2337
  } else {
2318
2338
  printDoctorReport(report, remoteCiDiagnostics);
2319
2339
  }
2320
- return doctorCommandShouldFailExit(report) ? 1 : 0;
2340
+ return doctorHasBlockingIssues(report) || doctorHasParityMismatch(report) ? 1 : 0;
2321
2341
  }
2322
2342
  case 'status': {
2323
2343
  const status = readLifecycleStatus();
@@ -2370,15 +2390,38 @@ export const runLifecycleCli = async (
2370
2390
  writeInfo(
2371
2391
  `[pumuki] hooks: pre-commit=${status.hookStatus['pre-commit'].managedBlockPresent ? 'managed' : 'missing'}, pre-push=${status.hookStatus['pre-push'].managedBlockPresent ? 'managed' : 'missing'}`
2372
2392
  );
2373
- printGovernanceConsoleHuman({
2374
- governanceObservation: status.governanceObservation,
2375
- governanceNextAction: status.governanceNextAction,
2376
- policyValidation: status.policyValidation,
2377
- experimentalFeatures: status.experimentalFeatures,
2378
- });
2379
2393
  writeInfo(
2380
2394
  `[pumuki] tracked node_modules paths: ${status.trackedNodeModulesCount}`
2381
2395
  );
2396
+ writeInfo(
2397
+ `[pumuki] policy-as-code: PRE_COMMIT=${status.policyValidation.stages.PRE_COMMIT.validationCode ?? 'n/a'} strict=${status.policyValidation.stages.PRE_COMMIT.strict ? 'yes' : 'no'} ` +
2398
+ `PRE_PUSH=${status.policyValidation.stages.PRE_PUSH.validationCode ?? 'n/a'} strict=${status.policyValidation.stages.PRE_PUSH.strict ? 'yes' : 'no'} ` +
2399
+ `CI=${status.policyValidation.stages.CI.validationCode ?? 'n/a'} strict=${status.policyValidation.stages.CI.strict ? 'yes' : 'no'}`
2400
+ );
2401
+ writeInfo(
2402
+ `[pumuki] experimental: ANALYTICS=${status.experimentalFeatures.features.analytics.mode} source=${status.experimentalFeatures.features.analytics.source} layer=${status.experimentalFeatures.features.analytics.layer} blocking=${status.experimentalFeatures.features.analytics.blocking ? 'yes' : 'no'} env=${status.experimentalFeatures.features.analytics.activationVariable}`
2403
+ );
2404
+ writeInfo(
2405
+ `[pumuki] experimental: HEURISTICS=${status.experimentalFeatures.features.heuristics.mode} source=${status.experimentalFeatures.features.heuristics.source} layer=${status.experimentalFeatures.features.heuristics.layer} blocking=${status.experimentalFeatures.features.heuristics.blocking ? 'yes' : 'no'} env=${status.experimentalFeatures.features.heuristics.activationVariable}`
2406
+ );
2407
+ writeInfo(
2408
+ `[pumuki] experimental: LEARNING_CONTEXT=${status.experimentalFeatures.features.learning_context.mode} source=${status.experimentalFeatures.features.learning_context.source} layer=${status.experimentalFeatures.features.learning_context.layer} blocking=${status.experimentalFeatures.features.learning_context.blocking ? 'yes' : 'no'} env=${status.experimentalFeatures.features.learning_context.activationVariable}`
2409
+ );
2410
+ writeInfo(
2411
+ `[pumuki] experimental: MCP_ENTERPRISE=${status.experimentalFeatures.features.mcp_enterprise.mode} source=${status.experimentalFeatures.features.mcp_enterprise.source} layer=${status.experimentalFeatures.features.mcp_enterprise.layer} blocking=${status.experimentalFeatures.features.mcp_enterprise.blocking ? 'yes' : 'no'} env=${status.experimentalFeatures.features.mcp_enterprise.activationVariable}`
2412
+ );
2413
+ writeInfo(
2414
+ `[pumuki] experimental: OPERATIONAL_MEMORY=${status.experimentalFeatures.features.operational_memory.mode} source=${status.experimentalFeatures.features.operational_memory.source} layer=${status.experimentalFeatures.features.operational_memory.layer} blocking=${status.experimentalFeatures.features.operational_memory.blocking ? 'yes' : 'no'} env=${status.experimentalFeatures.features.operational_memory.activationVariable}`
2415
+ );
2416
+ writeInfo(
2417
+ `[pumuki] experimental: PRE_WRITE=${status.experimentalFeatures.features.pre_write.mode} source=${status.experimentalFeatures.features.pre_write.source} layer=${status.experimentalFeatures.features.pre_write.layer} blocking=${status.experimentalFeatures.features.pre_write.blocking ? 'yes' : 'no'} env=${status.experimentalFeatures.features.pre_write.activationVariable}`
2418
+ );
2419
+ writeInfo(
2420
+ `[pumuki] experimental: SAAS_INGESTION=${status.experimentalFeatures.features.saas_ingestion.mode} source=${status.experimentalFeatures.features.saas_ingestion.source} layer=${status.experimentalFeatures.features.saas_ingestion.layer} blocking=${status.experimentalFeatures.features.saas_ingestion.blocking ? 'yes' : 'no'} env=${status.experimentalFeatures.features.saas_ingestion.activationVariable}`
2421
+ );
2422
+ writeInfo(
2423
+ `[pumuki] experimental: SDD=${status.experimentalFeatures.features.sdd.mode} source=${status.experimentalFeatures.features.sdd.source} layer=${status.experimentalFeatures.features.sdd.layer} blocking=${status.experimentalFeatures.features.sdd.blocking ? 'yes' : 'no'} env=${status.experimentalFeatures.features.sdd.activationVariable}`
2424
+ );
2382
2425
  if (remoteCiDiagnostics) {
2383
2426
  printRemoteCiDiagnostics(remoteCiDiagnostics);
2384
2427
  }
@@ -2718,9 +2761,6 @@ export const runLifecycleCli = async (
2718
2761
  `[pumuki] adapter files: ${result.changedFiles.join(', ')}`
2719
2762
  );
2720
2763
  }
2721
- writeInfo(
2722
- `[pumuki] adapter manifest: path=${result.bootstrapManifest.path} changed=${result.bootstrapManifest.changed ? 'yes' : 'no'}`
2723
- );
2724
2764
  }
2725
2765
  return 0;
2726
2766
  }
@@ -35,7 +35,8 @@ import {
35
35
  type PreWriteOpenSpecBootstrapTrace,
36
36
  buildPreWriteExperimentalDisabledResult,
37
37
  buildSddExperimentalEnableAdvisoryCommand,
38
- PRE_WRITE_ENABLE_STRICT_COMMAND,
38
+ runRawPreWriteAiGateCheck,
39
+ PRE_WRITE_ENABLE_ADVISORY_COMMAND,
39
40
  } from './cli';
40
41
 
41
42
  export const runSddCommand = async (parsed: ParsedArgs, activeDependencies: LifecycleCliDependencies): Promise<number> => {
@@ -83,7 +84,6 @@ export const runSddCommand = async (parsed: ParsedArgs, activeDependencies: Life
83
84
  const disabledResult = buildPreWriteExperimentalDisabledResult({
84
85
  stage: requestedStage,
85
86
  status: readSddStatus(process.cwd()),
86
- source: preWriteEnforcement.source,
87
87
  });
88
88
  if (parsed.json) {
89
89
  writeInfo(
@@ -106,7 +106,7 @@ export const runSddCommand = async (parsed: ParsedArgs, activeDependencies: Life
106
106
  },
107
107
  next_action: {
108
108
  reason: 'PRE_WRITE_EXPERIMENTAL_DISABLED',
109
- command: PRE_WRITE_ENABLE_STRICT_COMMAND,
109
+ command: PRE_WRITE_ENABLE_ADVISORY_COMMAND,
110
110
  },
111
111
  },
112
112
  null,
@@ -127,7 +127,7 @@ export const runSddCommand = async (parsed: ParsedArgs, activeDependencies: Life
127
127
  `[pumuki][sdd] pre-write enforcement: mode=${preWriteEnforcement.mode} source=${preWriteEnforcement.source} blocking=no`
128
128
  );
129
129
  writeInfo(
130
- `[pumuki][sdd] next action (PRE_WRITE_EXPERIMENTAL_DISABLED): ${PRE_WRITE_ENABLE_STRICT_COMMAND}`
130
+ `[pumuki][sdd] next action (PRE_WRITE_EXPERIMENTAL_DISABLED): ${PRE_WRITE_ENABLE_ADVISORY_COMMAND}`
131
131
  );
132
132
  }
133
133
  return 0;
@@ -195,9 +195,15 @@ export const runSddCommand = async (parsed: ParsedArgs, activeDependencies: Life
195
195
  automationTrace.attempted = auto.trace.attempted;
196
196
  automationTrace.actions = auto.trace.actions;
197
197
  }
198
+ const rawPreWriteAiGate = result.stage === 'PRE_WRITE' && aiGate
199
+ ? runRawPreWriteAiGateCheck({
200
+ repoRoot: process.cwd(),
201
+ requireMcpReceipt: true,
202
+ })
203
+ : null;
198
204
  const nextAction = resolvePreWriteNextAction({
199
205
  sdd: result,
200
- aiGate,
206
+ aiGate: rawPreWriteAiGate ?? aiGate,
201
207
  });
202
208
  const sddExperimentalNextAction =
203
209
  !aiGate && result.decision.code === 'SDD_EXPERIMENTAL_DISABLED'
@@ -209,10 +215,10 @@ export const runSddCommand = async (parsed: ParsedArgs, activeDependencies: Life
209
215
  if (parsed.json) {
210
216
  writeInfo(
211
217
  JSON.stringify(
212
- (aiGate)
218
+ (rawPreWriteAiGate ?? aiGate)
213
219
  ? buildPreWriteValidationEnvelope(
214
220
  result,
215
- aiGate!,
221
+ rawPreWriteAiGate ?? aiGate!,
216
222
  preWriteEnforcement,
217
223
  experimentalFeatures,
218
224
  policyValidation,
@@ -451,7 +457,6 @@ export const runSddCommand = async (parsed: ParsedArgs, activeDependencies: Life
451
457
  testStatus: parsed.sddEvidenceTestStatus,
452
458
  testOutputPath: parsed.sddEvidenceTestOutput,
453
459
  fromEvidencePath: parsed.sddEvidenceFromEvidence,
454
- traceabilityMarkdownPath: parsed.sddEvidenceTraceabilityMarkdown,
455
460
  });
456
461
  if (parsed.json) {
457
462
  writeInfo(JSON.stringify(evidenceResult, null, 2));
@@ -5,25 +5,10 @@ import { resolvePolicyForStage } from '../gate/stagePolicies';
5
5
  import { getPumukiHooksStatus, resolvePumukiHooksDirectory } from './hookManager';
6
6
  import { LifecycleGitService, type ILifecycleGitService } from './gitService';
7
7
  import { buildLifecycleVersionReport, getCurrentPumukiVersion } from './packageInfo';
8
- import {
9
- readLifecycleExperimentalFeaturesSnapshot,
10
- type LifecycleExperimentalFeaturesSnapshot,
11
- } from './experimentalFeaturesSnapshot';
12
8
  import {
13
9
  readLifecyclePolicyValidationSnapshot,
14
10
  type LifecyclePolicyValidationSnapshot,
15
11
  } from './policyValidationSnapshot';
16
- import {
17
- doctorGovernanceIsBlocking,
18
- doctorGovernanceNeedsAttention,
19
- readGovernanceObservationSnapshot,
20
- type GovernanceObservationSnapshot,
21
- } from './governanceObservationSnapshot';
22
- import {
23
- readGovernanceNextAction,
24
- type GovernanceNextActionReader,
25
- type GovernanceNextActionSummary,
26
- } from './governanceNextAction';
27
12
  import { readLifecycleState, type LifecycleState } from './state';
28
13
  import {
29
14
  detectOpenSpecInstallation,
@@ -110,9 +95,7 @@ export type LifecycleDoctorReport = {
110
95
  hooksDirectory: string;
111
96
  hooksDirectoryResolution: 'git-rev-parse' | 'git-config' | 'default';
112
97
  policyValidation: LifecyclePolicyValidationSnapshot;
113
- experimentalFeatures: LifecycleExperimentalFeaturesSnapshot;
114
- governanceObservation: GovernanceObservationSnapshot;
115
- governanceNextAction: GovernanceNextActionSummary;
98
+ policy_signature_remediation?: string;
116
99
  issues: ReadonlyArray<DoctorIssue>;
117
100
  deep?: DoctorDeepReport;
118
101
  parity_profile?: DoctorParityProfile;
@@ -810,12 +793,20 @@ const compareDoctorParityProfile = (params: {
810
793
  };
811
794
  };
812
795
 
796
+ const buildPolicySignatureRemediation = (
797
+ policyValidation: LifecyclePolicyValidationSnapshot
798
+ ): string | undefined => {
799
+ const mismatch = Object.values(policyValidation.stages).some(
800
+ (stage) => stage.validationCode === 'POLICY_AS_CODE_SIGNATURE_MISMATCH'
801
+ );
802
+ return mismatch ? 'pumuki policy reconcile --apply' : undefined;
803
+ };
804
+
813
805
  export const runLifecycleDoctor = (params?: {
814
806
  cwd?: string;
815
807
  git?: ILifecycleGitService;
816
808
  deep?: boolean;
817
809
  parity?: boolean;
818
- governanceNextActionReader?: GovernanceNextActionReader;
819
810
  }): LifecycleDoctorReport => {
820
811
  const git = params?.git ?? new LifecycleGitService();
821
812
  const cwd = params?.cwd ?? process.cwd();
@@ -843,19 +834,6 @@ export const runLifecycleDoctor = (params?: {
843
834
  repoRoot,
844
835
  lifecycleVersion: lifecycleState.version,
845
836
  });
846
- const policyValidation = readLifecyclePolicyValidationSnapshot(repoRoot);
847
- const experimentalFeatures = readLifecycleExperimentalFeaturesSnapshot();
848
- const governanceObservation = readGovernanceObservationSnapshot({
849
- repoRoot,
850
- experimentalFeatures,
851
- policyValidation,
852
- git,
853
- });
854
- const governanceNextAction = (params?.governanceNextActionReader ?? readGovernanceNextAction)({
855
- repoRoot,
856
- stage: 'PRE_WRITE',
857
- governanceObservation,
858
- });
859
837
 
860
838
  const parity_profile =
861
839
  params?.parity === true
@@ -869,6 +847,9 @@ export const runLifecycleDoctor = (params?: {
869
847
  ? compareDoctorParityProfile({ repoRoot, actual: parity_profile })
870
848
  : undefined;
871
849
 
850
+ const policyValidation = readLifecyclePolicyValidationSnapshot(repoRoot);
851
+ const policySignatureRemediation = buildPolicySignatureRemediation(policyValidation);
852
+
872
853
  return {
873
854
  repoRoot,
874
855
  packageVersion: version.effective,
@@ -879,9 +860,9 @@ export const runLifecycleDoctor = (params?: {
879
860
  hooksDirectory: hooksDirectory.path,
880
861
  hooksDirectoryResolution: hooksDirectory.source,
881
862
  policyValidation,
882
- experimentalFeatures,
883
- governanceNextAction,
884
- governanceObservation,
863
+ ...(policySignatureRemediation
864
+ ? { policy_signature_remediation: policySignatureRemediation }
865
+ : {}),
885
866
  issues,
886
867
  deep,
887
868
  parity_profile,
@@ -894,16 +875,3 @@ export const doctorHasBlockingIssues = (report: LifecycleDoctorReport): boolean
894
875
 
895
876
  export const doctorHasParityMismatch = (report: LifecycleDoctorReport): boolean =>
896
877
  typeof report.parity_comparison !== 'undefined' && report.parity_comparison.matches === false;
897
-
898
- export const doctorHasGovernanceAttention = (report: LifecycleDoctorReport): boolean =>
899
- doctorGovernanceNeedsAttention(report.governanceObservation);
900
-
901
- export const doctorCommandShouldWarnHuman = (report: LifecycleDoctorReport): boolean =>
902
- report.issues.length > 0
903
- || report.deep?.checks.some((check) => check.status !== 'pass') === true
904
- || doctorHasGovernanceAttention(report);
905
-
906
- export const doctorCommandShouldFailExit = (report: LifecycleDoctorReport): boolean =>
907
- doctorHasBlockingIssues(report)
908
- || doctorHasParityMismatch(report)
909
- || doctorGovernanceIsBlocking(report.governanceObservation);