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.
- package/AGENTS.md +269 -0
- package/CHANGELOG.md +697 -0
- package/README.md +4 -2
- package/VERSION +1 -1
- package/docs/README.md +13 -9
- package/docs/operations/RELEASE_NOTES.md +12 -76
- package/docs/product/HOW_IT_WORKS.md +6 -0
- package/docs/product/INSTALLATION.md +1 -1
- package/docs/product/USAGE.md +41 -4
- package/docs/tracking/plan-curso-pumuki-stack-my-architecture.md +118 -0
- package/docs/validation/README.md +6 -3
- package/integrations/config/skillsCustomRules.ts +18 -99
- package/integrations/evidence/buildEvidence.ts +0 -24
- package/integrations/evidence/repoState.ts +0 -3
- package/integrations/evidence/schema.ts +0 -18
- package/integrations/evidence/writeEvidence.ts +0 -24
- package/integrations/gate/evaluateAiGate.ts +15 -232
- package/integrations/gate/remediationCatalog.ts +0 -8
- package/integrations/git/GitService.ts +44 -5
- package/integrations/git/aiGateRepoPolicyFindings.ts +0 -4
- package/integrations/git/runPlatformGate.ts +1 -9
- package/integrations/git/runPlatformGateFacts.ts +19 -1
- package/integrations/git/runPlatformGateOutput.ts +27 -36
- package/integrations/lifecycle/adapter.templates.json +7 -13
- package/integrations/lifecycle/adapter.ts +0 -24
- package/integrations/lifecycle/artifacts.ts +1 -6
- package/integrations/lifecycle/audit.ts +101 -0
- package/integrations/lifecycle/cli.ts +110 -70
- package/integrations/lifecycle/cliSdd.ts +13 -8
- package/integrations/lifecycle/doctor.ts +16 -48
- package/integrations/lifecycle/hookManager.ts +0 -77
- package/integrations/lifecycle/index.ts +2 -0
- package/integrations/lifecycle/install.ts +0 -21
- package/integrations/lifecycle/npmService.ts +3 -155
- package/integrations/lifecycle/policyValidationSnapshot.ts +8 -2
- package/integrations/lifecycle/preWriteAutomation.ts +7 -77
- package/integrations/lifecycle/state.ts +1 -8
- package/integrations/lifecycle/status.ts +2 -29
- package/integrations/mcp/aiGateCheck.ts +26 -206
- package/integrations/mcp/autoExecuteAiStart.ts +87 -94
- package/integrations/mcp/enterpriseServer.ts +7 -23
- package/integrations/mcp/enterpriseStdioServer.cli.ts +4 -31
- package/integrations/mcp/preFlightCheck.ts +5 -51
- package/integrations/platform/detectPlatforms.ts +37 -0
- package/integrations/policy/experimentalFeatures.ts +1 -1
- package/integrations/sdd/evidenceScaffold.ts +2 -109
- package/package.json +10 -2
- package/scripts/check-tracking-single-active.sh +1 -1
- package/scripts/consumer-menu-matrix-baseline-report-lib.ts +13 -38
- package/scripts/consumer-postinstall-resolve-args.cjs +44 -0
- package/scripts/consumer-postinstall.cjs +76 -21
- package/scripts/framework-menu-advanced-view-lib.ts +0 -15
- package/scripts/framework-menu-consumer-actions-lib.ts +28 -4
- package/scripts/framework-menu-consumer-preflight-hints.ts +5 -2
- package/scripts/framework-menu-consumer-preflight-render.ts +0 -10
- package/scripts/framework-menu-consumer-preflight-run.ts +0 -23
- package/scripts/framework-menu-consumer-preflight-types.ts +0 -12
- package/scripts/framework-menu-consumer-runtime-actions.ts +87 -17
- package/scripts/framework-menu-consumer-runtime-audit.ts +36 -2
- package/scripts/framework-menu-consumer-runtime-evidence-classic.ts +140 -0
- package/scripts/framework-menu-consumer-runtime-lib.ts +2 -10
- package/scripts/framework-menu-consumer-runtime-menu.ts +4 -18
- package/scripts/framework-menu-consumer-runtime-types.ts +3 -3
- package/scripts/framework-menu-evidence-summary-lib.ts +1 -0
- package/scripts/framework-menu-evidence-summary-read.ts +57 -5
- package/scripts/framework-menu-evidence-summary-severity.ts +3 -1
- package/scripts/framework-menu-evidence-summary-types.ts +7 -0
- package/scripts/framework-menu-gate-lib.ts +9 -0
- package/scripts/framework-menu-layout-data.ts +5 -0
- package/scripts/framework-menu-matrix-baseline-lib.ts +15 -14
- package/scripts/framework-menu-matrix-canary-lib.ts +22 -1
- package/scripts/framework-menu-matrix-evidence-lib.ts +1 -0
- package/scripts/framework-menu-matrix-evidence-types.ts +13 -1
- package/scripts/framework-menu-matrix-runner-lib.ts +35 -0
- package/scripts/framework-menu-system-notifications-cause.ts +0 -24
- package/scripts/framework-menu-system-notifications-macos-swift-source.ts +24 -204
- package/scripts/framework-menu-system-notifications-macos.ts +4 -0
- package/scripts/framework-menu-system-notifications-payloads-blocked.ts +1 -1
- package/scripts/framework-menu-system-notifications-remediation.ts +13 -24
- package/scripts/framework-menu-system-notifications-text.ts +1 -7
- package/scripts/framework-menu.ts +3 -2
- package/scripts/package-install-smoke-consumer-git-repo-lib.ts +1 -10
- package/scripts/package-install-smoke-consumer-npm-lib.ts +9 -46
- package/scripts/pumuki-full-surface-smoke-lib.ts +37 -0
- package/scripts/pumuki-full-surface-smoke.ts +346 -0
- package/scripts/pumuki-smoke-installed-wrapper.cjs +31 -0
- package/integrations/evidence/trackingContract.ts +0 -150
- package/integrations/gate/governanceActionCatalog.ts +0 -275
- package/integrations/lifecycle/bootstrapManifest.ts +0 -248
- package/integrations/lifecycle/cliGovernanceConsole.ts +0 -69
- package/integrations/lifecycle/governanceNextAction.ts +0 -164
- package/integrations/lifecycle/governanceObservationSnapshot.ts +0 -613
- package/integrations/mcp/alignedPlatformGate.ts +0 -232
- package/integrations/mcp/readMcpPrePushStdin.ts +0 -7
- package/scripts/build-ruralgo-s1-evidence-pack.ts +0 -85
- 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>] [--
|
|
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>] [--
|
|
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
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
policyValidation
|
|
1542
|
-
|
|
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 =
|
|
1577
|
-
|
|
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
|
|
1635
|
-
'PUMUKI_EXPERIMENTAL_PRE_WRITE=
|
|
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
|
|
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:
|
|
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:
|
|
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
|
|
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
|
-
|
|
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:
|
|
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): ${
|
|
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
|
-
|
|
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
|
-
|
|
883
|
-
|
|
884
|
-
|
|
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);
|