pumuki 6.3.129 → 6.3.130
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 +16 -1
- package/CHANGELOG.md +9 -0
- package/README.md +14 -10
- package/VERSION +1 -1
- package/core/facts/detectors/text/android.test.ts +2583 -24
- package/core/facts/detectors/text/android.ts +4633 -34
- package/core/facts/detectors/typescript/index.test.ts +3639 -73
- package/core/facts/detectors/typescript/index.ts +4819 -270
- package/core/facts/extractHeuristicFacts.ts +271 -6
- package/core/rules/presets/heuristics/android.test.ts +314 -1
- package/core/rules/presets/heuristics/android.ts +1220 -50
- package/core/rules/presets/heuristics/typescript.test.ts +158 -2
- package/core/rules/presets/heuristics/typescript.ts +508 -0
- package/docs/README.md +3 -3
- package/docs/operations/RELEASE_NOTES.md +7 -1
- package/docs/operations/framework-menu-consumer-walkthrough.md +18 -15
- package/docs/product/API_REFERENCE.md +1 -1
- package/docs/product/USAGE.md +1 -1
- package/docs/validation/README.md +3 -1
- package/integrations/config/skillsCompilerTemplates.test.ts +131 -0
- package/integrations/config/skillsCompilerTemplates.ts +953 -7
- package/integrations/config/skillsDetectorRegistry.ts +451 -8
- package/integrations/config/skillsMarkdownRules.ts +884 -2
- package/integrations/evidence/buildEvidence.ts +29 -1
- package/integrations/evidence/platformSummary.test.ts +73 -9
- package/integrations/evidence/platformSummary.ts +165 -7
- package/integrations/evidence/repoState.ts +3 -0
- package/integrations/evidence/schema.ts +18 -0
- package/integrations/evidence/trackingContract.ts +17 -0
- package/integrations/evidence/writeEvidence.test.ts +3 -0
- package/integrations/evidence/writeEvidence.ts +29 -1
- package/integrations/gate/evaluateAiGate.ts +251 -8
- package/integrations/gate/governanceActionCatalog.ts +275 -0
- package/integrations/gate/remediationCatalog.ts +8 -0
- package/integrations/git/runPlatformGate.ts +9 -1
- package/integrations/lifecycle/adapter.ts +24 -0
- package/integrations/lifecycle/bootstrapManifest.ts +248 -0
- package/integrations/lifecycle/cliGovernanceConsole.ts +69 -0
- package/integrations/lifecycle/governanceNextAction.ts +171 -0
- package/integrations/lifecycle/governanceObservationSnapshot.ts +369 -0
- package/integrations/lifecycle/packageInfo.ts +118 -1
- package/integrations/lifecycle/state.ts +8 -1
- package/integrations/lifecycle/trackingState.ts +403 -0
- package/integrations/lifecycle/watch.ts +1 -1
- package/integrations/mcp/aiGateCheck.ts +194 -10
- package/integrations/mcp/alignedPlatformGate.ts +232 -0
- package/integrations/mcp/enterpriseServer.ts +19 -3
- package/integrations/mcp/preFlightCheck.ts +66 -3
- package/integrations/mcp/readMcpPrePushStdin.ts +7 -0
- package/package.json +1 -1
- package/scripts/build-ruralgo-s1-evidence-pack.ts +85 -0
- package/scripts/check-tracking-single-active.sh +1 -1
- package/scripts/framework-menu-advanced-view-lib.ts +49 -0
- package/scripts/framework-menu-consumer-actions-lib.ts +32 -32
- package/scripts/framework-menu-consumer-preflight-render.ts +10 -0
- package/scripts/framework-menu-consumer-preflight-run.ts +23 -0
- package/scripts/framework-menu-consumer-preflight-types.ts +12 -0
- package/scripts/framework-menu-consumer-runtime-actions.ts +11 -5
- package/scripts/framework-menu-consumer-runtime-audit.ts +0 -28
- package/scripts/framework-menu-consumer-runtime-evidence-classic.ts +118 -42
- package/scripts/framework-menu-consumer-runtime-lib.ts +38 -0
- package/scripts/framework-menu-consumer-runtime-menu.ts +55 -15
- package/scripts/framework-menu-consumer-runtime-types.ts +4 -0
- package/scripts/framework-menu-evidence-summary-read.ts +17 -1
- package/scripts/framework-menu-evidence-summary-types.ts +3 -0
- package/scripts/framework-menu-layout-data.ts +3 -23
- package/scripts/framework-menu-system-notifications-macos-applescript-dialog.ts +1 -1
- package/scripts/framework-menu-system-notifications-macos-dialog-payload.ts +14 -2
- package/scripts/framework-menu-system-notifications-macos-swift-source.ts +1 -1
- package/scripts/framework-menu-system-notifications-payloads-blocked.ts +128 -4
- package/scripts/framework-menu-system-notifications-payloads.ts +8 -1
- package/scripts/framework-menu-system-notifications-text.ts +7 -1
- package/scripts/framework-menu.ts +37 -2
- package/scripts/package-install-smoke-consumer-git-repo-lib.ts +10 -1
- package/scripts/package-install-smoke-consumer-npm-lib.ts +46 -9
- package/scripts/ruralgo-s1-evidence-pack-lib.ts +200 -0
- package/skills.lock.json +613 -698
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import type { AiGateStage } from '../gate/evaluateAiGate';
|
|
2
|
+
import { resolvePolicyForStage } from '../gate/stagePolicies';
|
|
3
|
+
import type { SddDecision } from '../sdd';
|
|
4
|
+
import { GitService } from '../git/GitService';
|
|
5
|
+
import { runPlatformGate } from '../git/runPlatformGate';
|
|
6
|
+
import type { GateScope } from '../git/runPlatformGateFacts';
|
|
7
|
+
import { readMcpPrePushStdin } from './readMcpPrePushStdin';
|
|
8
|
+
|
|
9
|
+
const ZERO_HASH = /^0+$/;
|
|
10
|
+
|
|
11
|
+
const runGit = (repoRoot: string, args: ReadonlyArray<string>): string | null => {
|
|
12
|
+
try {
|
|
13
|
+
return new GitService().runGit(args, repoRoot).trim();
|
|
14
|
+
} catch {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const resolveUpstreamRefInRepo = (repoRoot: string): string | null =>
|
|
20
|
+
runGit(repoRoot, ['rev-parse', '@{u}']);
|
|
21
|
+
|
|
22
|
+
const resolveHeadOidInRepo = (repoRoot: string): string | null =>
|
|
23
|
+
runGit(repoRoot, ['rev-parse', 'HEAD']);
|
|
24
|
+
|
|
25
|
+
const resolveCiBaseRefInRepo = (repoRoot: string): string => {
|
|
26
|
+
const fromEnv = process.env.GITHUB_BASE_REF?.trim();
|
|
27
|
+
if (fromEnv) {
|
|
28
|
+
if (runGit(repoRoot, ['rev-parse', '--verify', fromEnv])) {
|
|
29
|
+
return fromEnv;
|
|
30
|
+
}
|
|
31
|
+
const remoteRef = `origin/${fromEnv}`;
|
|
32
|
+
if (runGit(repoRoot, ['rev-parse', '--verify', remoteRef])) {
|
|
33
|
+
return remoteRef;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
for (const candidate of ['origin/main', 'main', 'HEAD']) {
|
|
38
|
+
if (runGit(repoRoot, ['rev-parse', '--verify', candidate])) {
|
|
39
|
+
return candidate;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return 'HEAD';
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const resolvePrePushBootstrapBaseRefInRepo = (repoRoot: string): string => {
|
|
47
|
+
const candidates = ['origin/develop', 'develop', resolveCiBaseRefInRepo(repoRoot)];
|
|
48
|
+
for (const candidate of candidates) {
|
|
49
|
+
if (runGit(repoRoot, ['rev-parse', '--verify', candidate])) {
|
|
50
|
+
return candidate;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return 'HEAD';
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const shouldAllowBootstrapPrePush = (rawInput: string): boolean => {
|
|
58
|
+
const lines = rawInput
|
|
59
|
+
.split('\n')
|
|
60
|
+
.map((line) => line.trim())
|
|
61
|
+
.filter((line) => line.length > 0);
|
|
62
|
+
|
|
63
|
+
for (const line of lines) {
|
|
64
|
+
const [localRef, localOid, remoteRef, remoteOid] = line.split(/\s+/);
|
|
65
|
+
if (!localRef || !localOid || !remoteRef || !remoteOid) {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
const localIsBranch = localRef.startsWith('refs/heads/');
|
|
69
|
+
const remoteIsBranch = remoteRef.startsWith('refs/heads/');
|
|
70
|
+
const localIsDeletion = ZERO_HASH.test(localOid);
|
|
71
|
+
const remoteIsNewBranch = ZERO_HASH.test(remoteOid);
|
|
72
|
+
|
|
73
|
+
if (localIsBranch && remoteIsBranch && !localIsDeletion && remoteIsNewBranch) {
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return false;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const resolveExplicitPrePushRange = (
|
|
82
|
+
rawInput: string
|
|
83
|
+
): { fromRef: string; toRef: string } | undefined => {
|
|
84
|
+
const lines = rawInput
|
|
85
|
+
.split('\n')
|
|
86
|
+
.map((line) => line.trim())
|
|
87
|
+
.filter((line) => line.length > 0);
|
|
88
|
+
|
|
89
|
+
const eligibleRanges = lines
|
|
90
|
+
.map((line) => {
|
|
91
|
+
const [localRef, localOid, remoteRef, remoteOid] = line.split(/\s+/);
|
|
92
|
+
if (!localRef || !localOid || !remoteRef || !remoteOid) {
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
const localIsDeletion = ZERO_HASH.test(localOid);
|
|
96
|
+
const remoteIsNewBranch = ZERO_HASH.test(remoteOid);
|
|
97
|
+
if (localIsDeletion || remoteIsNewBranch) {
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
fromRef: remoteOid,
|
|
102
|
+
toRef: localOid,
|
|
103
|
+
};
|
|
104
|
+
})
|
|
105
|
+
.filter((value): value is { fromRef: string; toRef: string } => Boolean(value));
|
|
106
|
+
|
|
107
|
+
if (eligibleRanges.length !== 1) {
|
|
108
|
+
return undefined;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return eligibleRanges[0];
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
type PrePushScopeResolution =
|
|
115
|
+
| { kind: 'scope'; scope: GateScope; sddDecisionOverride?: Pick<SddDecision, 'allowed' | 'code' | 'message'> }
|
|
116
|
+
| { kind: 'upstream_missing' };
|
|
117
|
+
|
|
118
|
+
const resolvePrePushScopeForMcp = (params: { repoRoot: string }): PrePushScopeResolution => {
|
|
119
|
+
const prePushInput = readMcpPrePushStdin();
|
|
120
|
+
const upstreamRef = resolveUpstreamRefInRepo(params.repoRoot);
|
|
121
|
+
if (!upstreamRef) {
|
|
122
|
+
const bootstrapBaseRef = resolvePrePushBootstrapBaseRefInRepo(params.repoRoot);
|
|
123
|
+
const bootstrapByPrePushStdIn = shouldAllowBootstrapPrePush(prePushInput);
|
|
124
|
+
const bootstrapByFallbackBase = !bootstrapByPrePushStdIn && bootstrapBaseRef !== 'HEAD';
|
|
125
|
+
const manualInvocationFallback =
|
|
126
|
+
!bootstrapByPrePushStdIn &&
|
|
127
|
+
!bootstrapByFallbackBase &&
|
|
128
|
+
prePushInput.trim().length === 0;
|
|
129
|
+
if (bootstrapByPrePushStdIn || bootstrapByFallbackBase) {
|
|
130
|
+
return {
|
|
131
|
+
kind: 'scope',
|
|
132
|
+
scope: {
|
|
133
|
+
kind: 'range',
|
|
134
|
+
fromRef: bootstrapBaseRef,
|
|
135
|
+
toRef: 'HEAD',
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
if (manualInvocationFallback) {
|
|
140
|
+
return { kind: 'scope', scope: { kind: 'workingTree' } };
|
|
141
|
+
}
|
|
142
|
+
return { kind: 'upstream_missing' };
|
|
143
|
+
}
|
|
144
|
+
const explicitPrePushRange = resolveExplicitPrePushRange(prePushInput);
|
|
145
|
+
const prePushFromRef = explicitPrePushRange?.fromRef ?? upstreamRef;
|
|
146
|
+
const prePushToRef = explicitPrePushRange?.toRef ?? 'HEAD';
|
|
147
|
+
const headOid = resolveHeadOidInRepo(params.repoRoot);
|
|
148
|
+
const sddDecisionOverride =
|
|
149
|
+
explicitPrePushRange && headOid && explicitPrePushRange.toRef !== headOid
|
|
150
|
+
? ({
|
|
151
|
+
allowed: true,
|
|
152
|
+
code: 'ALLOWED',
|
|
153
|
+
message:
|
|
154
|
+
`SDD enforcement suspended for PRE_PUSH historical publish targeting ${explicitPrePushRange.toRef.slice(0, 12)} ` +
|
|
155
|
+
`instead of current HEAD ${headOid.slice(0, 12)}.`,
|
|
156
|
+
} as Pick<SddDecision, 'allowed' | 'code' | 'message'>)
|
|
157
|
+
: undefined;
|
|
158
|
+
return {
|
|
159
|
+
kind: 'scope',
|
|
160
|
+
scope: {
|
|
161
|
+
kind: 'range',
|
|
162
|
+
fromRef: prePushFromRef,
|
|
163
|
+
toRef: prePushToRef,
|
|
164
|
+
},
|
|
165
|
+
sddDecisionOverride,
|
|
166
|
+
};
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
type RunAlignedParams = {
|
|
170
|
+
repoRoot: string;
|
|
171
|
+
stage: AiGateStage;
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
export const runMcpAlignedPlatformGate = async (
|
|
175
|
+
params: RunAlignedParams
|
|
176
|
+
): Promise<{ exitCode: number; aligned: boolean; skipReason: string | null }> => {
|
|
177
|
+
const git = new GitService();
|
|
178
|
+
const resolved = resolvePolicyForStage(params.stage, params.repoRoot);
|
|
179
|
+
if (params.stage === 'PRE_WRITE') {
|
|
180
|
+
const exitCode = await runPlatformGate({
|
|
181
|
+
policy: resolved.policy,
|
|
182
|
+
policyTrace: resolved.trace,
|
|
183
|
+
scope: { kind: 'workingTree' },
|
|
184
|
+
silent: true,
|
|
185
|
+
services: { git },
|
|
186
|
+
});
|
|
187
|
+
return { exitCode, aligned: true, skipReason: null };
|
|
188
|
+
}
|
|
189
|
+
if (params.stage === 'PRE_COMMIT') {
|
|
190
|
+
const exitCode = await runPlatformGate({
|
|
191
|
+
policy: resolved.policy,
|
|
192
|
+
policyTrace: resolved.trace,
|
|
193
|
+
scope: { kind: 'staged' },
|
|
194
|
+
silent: true,
|
|
195
|
+
services: { git },
|
|
196
|
+
});
|
|
197
|
+
return { exitCode, aligned: true, skipReason: null };
|
|
198
|
+
}
|
|
199
|
+
if (params.stage === 'CI') {
|
|
200
|
+
const ciBaseRef = resolveCiBaseRefInRepo(params.repoRoot);
|
|
201
|
+
const exitCode = await runPlatformGate({
|
|
202
|
+
policy: resolved.policy,
|
|
203
|
+
policyTrace: resolved.trace,
|
|
204
|
+
scope: {
|
|
205
|
+
kind: 'range',
|
|
206
|
+
fromRef: ciBaseRef,
|
|
207
|
+
toRef: 'HEAD',
|
|
208
|
+
},
|
|
209
|
+
silent: true,
|
|
210
|
+
services: { git },
|
|
211
|
+
});
|
|
212
|
+
return { exitCode, aligned: true, skipReason: null };
|
|
213
|
+
}
|
|
214
|
+
if (params.stage === 'PRE_PUSH') {
|
|
215
|
+
const scopeResolution = resolvePrePushScopeForMcp({ repoRoot: params.repoRoot });
|
|
216
|
+
if (scopeResolution.kind === 'upstream_missing') {
|
|
217
|
+
return { exitCode: 1, aligned: false, skipReason: 'PRE_PUSH_UPSTREAM_MISSING' };
|
|
218
|
+
}
|
|
219
|
+
const exitCode = await runPlatformGate({
|
|
220
|
+
policy: resolved.policy,
|
|
221
|
+
policyTrace: resolved.trace,
|
|
222
|
+
scope: scopeResolution.scope,
|
|
223
|
+
silent: true,
|
|
224
|
+
services: { git },
|
|
225
|
+
...(scopeResolution.sddDecisionOverride
|
|
226
|
+
? { sddDecisionOverride: scopeResolution.sddDecisionOverride }
|
|
227
|
+
: {}),
|
|
228
|
+
});
|
|
229
|
+
return { exitCode, aligned: true, skipReason: null };
|
|
230
|
+
}
|
|
231
|
+
throw new Error(`Unsupported MCP aligned stage: ${String(params.stage)}`);
|
|
232
|
+
};
|
|
@@ -10,7 +10,7 @@ import { resolveMcpEnterpriseExperimentalFeature } from '../policy/experimentalF
|
|
|
10
10
|
import { evaluateSddPolicy, readSddStatus } from '../sdd';
|
|
11
11
|
import type { SddStage } from '../sdd';
|
|
12
12
|
import { toStatusPayload } from './evidencePayloads';
|
|
13
|
-
import {
|
|
13
|
+
import { runEnterpriseAiGateCheckAsync } from './aiGateCheck';
|
|
14
14
|
import { runEnterprisePreFlightCheck } from './preFlightCheck';
|
|
15
15
|
import { runEnterpriseAutoExecuteAiStart } from './autoExecuteAiStart';
|
|
16
16
|
import { writeMcpAiGateReceipt } from './aiGateReceipt';
|
|
@@ -40,6 +40,14 @@ type EnterpriseStatusPayload = {
|
|
|
40
40
|
evidence: ReturnType<typeof toStatusPayload>;
|
|
41
41
|
};
|
|
42
42
|
|
|
43
|
+
type EnterpriseHealthPayload = {
|
|
44
|
+
status: 'ok';
|
|
45
|
+
repoRoot: string;
|
|
46
|
+
experimentalFeatures: {
|
|
47
|
+
mcp_enterprise: ReturnType<typeof resolveMcpEnterpriseExperimentalFeature>;
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
|
|
43
51
|
const ENTERPRISE_RESOURCES = [
|
|
44
52
|
'evidence://status',
|
|
45
53
|
'gitflow://state',
|
|
@@ -443,7 +451,7 @@ const executeEnterpriseTool = async (
|
|
|
443
451
|
}
|
|
444
452
|
case 'ai_gate_check': {
|
|
445
453
|
const stage = toSddStage(args.stage, 'PRE_COMMIT');
|
|
446
|
-
const execution =
|
|
454
|
+
const execution = await runEnterpriseAiGateCheckAsync({
|
|
447
455
|
repoRoot,
|
|
448
456
|
stage,
|
|
449
457
|
});
|
|
@@ -702,6 +710,14 @@ const buildStatusPayload = (repoRoot: string): EnterpriseStatusPayload => ({
|
|
|
702
710
|
evidence: toStatusPayload(repoRoot),
|
|
703
711
|
});
|
|
704
712
|
|
|
713
|
+
const buildHealthPayload = (repoRoot: string): EnterpriseHealthPayload => ({
|
|
714
|
+
status: 'ok',
|
|
715
|
+
repoRoot,
|
|
716
|
+
experimentalFeatures: {
|
|
717
|
+
mcp_enterprise: readMcpEnterpriseExperimentalState(),
|
|
718
|
+
},
|
|
719
|
+
});
|
|
720
|
+
|
|
705
721
|
export const startEnterpriseMcpServer = (
|
|
706
722
|
options: EnterpriseServerOptions = {}
|
|
707
723
|
): EnterpriseServerHandle => {
|
|
@@ -732,7 +748,7 @@ export const startEnterpriseMcpServer = (
|
|
|
732
748
|
sendJson(res, 405, { error: 'Method not allowed' });
|
|
733
749
|
return;
|
|
734
750
|
}
|
|
735
|
-
sendJson(res, 200,
|
|
751
|
+
sendJson(res, 200, buildHealthPayload(repoRoot));
|
|
736
752
|
return;
|
|
737
753
|
}
|
|
738
754
|
|
|
@@ -1,6 +1,12 @@
|
|
|
1
|
+
import {
|
|
2
|
+
resolveGovernanceCatalogAction,
|
|
3
|
+
type GovernanceCatalogNextAction,
|
|
4
|
+
} from '../gate/governanceActionCatalog';
|
|
1
5
|
import { evaluateAiGate, type AiGateStage, type AiGateViolation } from '../gate/evaluateAiGate';
|
|
2
6
|
import { collectWorktreeAtomicSlices } from '../git/worktreeAtomicSlices';
|
|
7
|
+
import { readLifecyclePolicyValidationSnapshot } from '../lifecycle/policyValidationSnapshot';
|
|
3
8
|
import { resolveLearningContextExperimentalFeature } from '../policy/experimentalFeatures';
|
|
9
|
+
import { resolvePreWriteEnforcement } from '../policy/preWriteEnforcement';
|
|
4
10
|
import { readSddLearningContext, type SddLearningContext } from '../sdd/learningInsights';
|
|
5
11
|
|
|
6
12
|
const ACTIONABLE_HINTS_BY_CODE: Readonly<Record<string, string>> = {
|
|
@@ -39,6 +45,28 @@ const ACTIONABLE_HINTS_BY_CODE: Readonly<Record<string, string>> = {
|
|
|
39
45
|
'Mapea todas las reglas AUTO a detectores AST antes de continuar.',
|
|
40
46
|
EVIDENCE_TIMESTAMP_FUTURE: 'Corrige la hora del sistema y regenera evidencia.',
|
|
41
47
|
GITFLOW_PROTECTED_BRANCH: 'Evita trabajo directo en ramas protegidas (usa feature/*).',
|
|
48
|
+
GITFLOW_BRANCH_NAMING_INVALID:
|
|
49
|
+
'La rama actual no cumple GitFlow. Usa feature/*, bugfix/*, hotfix/*, release/*, chore/*, refactor/* o docs/*.',
|
|
50
|
+
TRACKING_CANONICAL_SOURCE_CONFLICT:
|
|
51
|
+
'AGENTS.md y los README del repo no apuntan a la misma fuente canónica de tracking.',
|
|
52
|
+
TRACKING_CANONICAL_FILE_MISSING:
|
|
53
|
+
'El repo declara un MD de tracking canónico que ahora mismo no existe.',
|
|
54
|
+
TRACKING_CANONICAL_IN_PROGRESS_INVALID:
|
|
55
|
+
'El MD canónico de tracking debe dejar exactamente una task o fase en construcción.',
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const normalizeGovernanceCatalogCode = (code: string): string => {
|
|
59
|
+
switch (code) {
|
|
60
|
+
case 'EVIDENCE_INVALID':
|
|
61
|
+
case 'EVIDENCE_CHAIN_INVALID':
|
|
62
|
+
return 'EVIDENCE_INVALID_OR_CHAIN';
|
|
63
|
+
case 'GITFLOW_PROTECTED_BRANCH':
|
|
64
|
+
return 'GITFLOW_PROTECTED_BRANCH_CONTEXT';
|
|
65
|
+
case 'GITFLOW_BRANCH_NAMING_INVALID':
|
|
66
|
+
return 'GITFLOW_BRANCH_NAMING_INVALID_CONTEXT';
|
|
67
|
+
default:
|
|
68
|
+
return code;
|
|
69
|
+
}
|
|
42
70
|
};
|
|
43
71
|
|
|
44
72
|
const buildPreFlightHints = (params: {
|
|
@@ -115,6 +143,14 @@ export type EnterprisePreFlightCheckResult = {
|
|
|
115
143
|
phase: 'GREEN' | 'RED';
|
|
116
144
|
message: string;
|
|
117
145
|
instruction: string;
|
|
146
|
+
reason_code: string;
|
|
147
|
+
prewrite_effective: {
|
|
148
|
+
mode: ReturnType<typeof resolvePreWriteEnforcement>['mode'];
|
|
149
|
+
source: ReturnType<typeof resolvePreWriteEnforcement>['source'];
|
|
150
|
+
blocking: boolean;
|
|
151
|
+
strict_policy: boolean;
|
|
152
|
+
};
|
|
153
|
+
next_action: GovernanceCatalogNextAction;
|
|
118
154
|
stage: ReturnType<typeof evaluateAiGate>['stage'];
|
|
119
155
|
policy: ReturnType<typeof evaluateAiGate>['policy'];
|
|
120
156
|
violations: ReturnType<typeof evaluateAiGate>['violations'];
|
|
@@ -145,6 +181,8 @@ export const runEnterprisePreFlightCheck = (params: {
|
|
|
145
181
|
: readSddLearningContext({
|
|
146
182
|
repoRoot: params.repoRoot,
|
|
147
183
|
});
|
|
184
|
+
const preWriteEnforcement = resolvePreWriteEnforcement();
|
|
185
|
+
const policyValidation = readLifecyclePolicyValidationSnapshot(params.repoRoot);
|
|
148
186
|
|
|
149
187
|
const hints = buildPreFlightHints({
|
|
150
188
|
repoRoot: params.repoRoot,
|
|
@@ -154,13 +192,30 @@ export const runEnterprisePreFlightCheck = (params: {
|
|
|
154
192
|
upstream: evaluation.repo_state.git.upstream,
|
|
155
193
|
learningContext,
|
|
156
194
|
});
|
|
195
|
+
const firstViolation = evaluation.violations[0];
|
|
196
|
+
const reasonCode = firstViolation?.code ?? 'READY';
|
|
197
|
+
const governanceAction = firstViolation
|
|
198
|
+
? resolveGovernanceCatalogAction({
|
|
199
|
+
code: normalizeGovernanceCatalogCode(firstViolation.code),
|
|
200
|
+
stage: evaluation.stage,
|
|
201
|
+
})
|
|
202
|
+
: resolveGovernanceCatalogAction({
|
|
203
|
+
code: 'READY',
|
|
204
|
+
stage: evaluation.stage,
|
|
205
|
+
});
|
|
157
206
|
const phase: 'GREEN' | 'RED' = evaluation.allowed ? 'GREEN' : 'RED';
|
|
158
207
|
const message = evaluation.allowed
|
|
159
208
|
? '✅ Pre-flight aprobado: puedes continuar con la implementación.'
|
|
160
|
-
: `🔴 Pre-flight bloqueado: corrige ${
|
|
161
|
-
const instruction = evaluation.allowed
|
|
209
|
+
: `🔴 Pre-flight bloqueado: corrige ${reasonCode} y vuelve a ejecutar.`;
|
|
210
|
+
const instruction = !firstViolation && evaluation.allowed
|
|
162
211
|
? 'Implementa el cambio mínimo para pasar en verde y vuelve a validar.'
|
|
163
|
-
:
|
|
212
|
+
: governanceAction.instruction;
|
|
213
|
+
const nextAction: GovernanceCatalogNextAction = evaluation.allowed
|
|
214
|
+
? {
|
|
215
|
+
kind: 'info',
|
|
216
|
+
message: governanceAction.next_action.message,
|
|
217
|
+
}
|
|
218
|
+
: governanceAction.next_action;
|
|
164
219
|
|
|
165
220
|
return {
|
|
166
221
|
tool: 'pre_flight_check',
|
|
@@ -173,6 +228,14 @@ export const runEnterprisePreFlightCheck = (params: {
|
|
|
173
228
|
phase,
|
|
174
229
|
message,
|
|
175
230
|
instruction,
|
|
231
|
+
reason_code: reasonCode,
|
|
232
|
+
prewrite_effective: {
|
|
233
|
+
mode: preWriteEnforcement.mode,
|
|
234
|
+
source: preWriteEnforcement.source,
|
|
235
|
+
blocking: preWriteEnforcement.blocking,
|
|
236
|
+
strict_policy: policyValidation.stages.PRE_WRITE.strict,
|
|
237
|
+
},
|
|
238
|
+
next_action: nextAction,
|
|
176
239
|
stage: evaluation.stage,
|
|
177
240
|
policy: evaluation.policy,
|
|
178
241
|
violations: evaluation.violations,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pumuki",
|
|
3
|
-
"version": "6.3.
|
|
3
|
+
"version": "6.3.130",
|
|
4
4
|
"description": "Enterprise-grade AST Intelligence System with multi-platform support (iOS, Android, Backend, Frontend) and Feature-First + DDD + Clean Architecture enforcement. Includes dynamic violations API for intelligent querying.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildRuralGoS1EvidencePackMarkdown,
|
|
3
|
+
writeRuralGoS1EvidencePack,
|
|
4
|
+
} from './ruralgo-s1-evidence-pack-lib';
|
|
5
|
+
|
|
6
|
+
type CliOptions = {
|
|
7
|
+
consumerRoot: string;
|
|
8
|
+
outFile: string;
|
|
9
|
+
packageVersion: string;
|
|
10
|
+
generatedAt: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const parseArgs = (argv: ReadonlyArray<string>): CliOptions => {
|
|
14
|
+
const options: CliOptions = {
|
|
15
|
+
consumerRoot: '<RURALGO_REPO_ROOT>',
|
|
16
|
+
outFile: '.audit-reports/ruralgo-s1/ruralgo-s1-evidence-pack.md',
|
|
17
|
+
packageVersion: 'unknown',
|
|
18
|
+
generatedAt: new Date().toISOString(),
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
22
|
+
const token = argv[index];
|
|
23
|
+
const next = argv[index + 1];
|
|
24
|
+
switch (token) {
|
|
25
|
+
case '--consumer-root':
|
|
26
|
+
if (!next) {
|
|
27
|
+
throw new Error('missing value for --consumer-root');
|
|
28
|
+
}
|
|
29
|
+
options.consumerRoot = next;
|
|
30
|
+
index += 1;
|
|
31
|
+
break;
|
|
32
|
+
case '--out':
|
|
33
|
+
if (!next) {
|
|
34
|
+
throw new Error('missing value for --out');
|
|
35
|
+
}
|
|
36
|
+
options.outFile = next;
|
|
37
|
+
index += 1;
|
|
38
|
+
break;
|
|
39
|
+
case '--package-version':
|
|
40
|
+
if (!next) {
|
|
41
|
+
throw new Error('missing value for --package-version');
|
|
42
|
+
}
|
|
43
|
+
options.packageVersion = next;
|
|
44
|
+
index += 1;
|
|
45
|
+
break;
|
|
46
|
+
case '--generated-at':
|
|
47
|
+
if (!next) {
|
|
48
|
+
throw new Error('missing value for --generated-at');
|
|
49
|
+
}
|
|
50
|
+
options.generatedAt = next;
|
|
51
|
+
index += 1;
|
|
52
|
+
break;
|
|
53
|
+
default:
|
|
54
|
+
throw new Error(`unknown argument: ${token}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return options;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const main = (): number => {
|
|
62
|
+
const cwd = process.cwd();
|
|
63
|
+
const options = parseArgs(process.argv.slice(2));
|
|
64
|
+
const markdown = buildRuralGoS1EvidencePackMarkdown({
|
|
65
|
+
cwd,
|
|
66
|
+
consumerRoot: options.consumerRoot,
|
|
67
|
+
packageVersion: options.packageVersion,
|
|
68
|
+
generatedAt: options.generatedAt,
|
|
69
|
+
});
|
|
70
|
+
const outputPath = writeRuralGoS1EvidencePack({
|
|
71
|
+
cwd,
|
|
72
|
+
outFile: options.outFile,
|
|
73
|
+
markdown,
|
|
74
|
+
});
|
|
75
|
+
process.stdout.write(`ruralgo s1 evidence pack generated at ${outputPath}\n`);
|
|
76
|
+
return 0;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
try {
|
|
80
|
+
process.exitCode = main();
|
|
81
|
+
} catch (error) {
|
|
82
|
+
const message = error instanceof Error ? error.message : 'unknown error';
|
|
83
|
+
process.stderr.write(`ruralgo s1 evidence pack failed: ${message}\n`);
|
|
84
|
+
process.exitCode = 1;
|
|
85
|
+
}
|
|
@@ -31,7 +31,7 @@ for FILE in "${FILES[@]}"; do
|
|
|
31
31
|
fi
|
|
32
32
|
|
|
33
33
|
if [[ "${FILE}" == "PUMUKI-RESET-MASTER-PLAN.md" ]]; then
|
|
34
|
-
ACTIVE_PATTERN='^- Estado
|
|
34
|
+
ACTIVE_PATTERN='(^- Estado:\s*🚧(?:\s|$))|(^`?\[\s*🚧\s*\]\s*-`?)|(^\|\s*[^|]+\|\s*`?\[\s*🚧\s*\]\s*-`?)|(^\|\s*🚧(?:\s|\|))'
|
|
35
35
|
else
|
|
36
36
|
ACTIVE_PATTERN='^- 🚧 (`?P[0-9A-Za-z.-]+`?)'
|
|
37
37
|
fi
|
|
@@ -19,20 +19,47 @@ import {
|
|
|
19
19
|
renderActionRow,
|
|
20
20
|
renderBadge,
|
|
21
21
|
} from './framework-menu-ui-components-lib';
|
|
22
|
+
import {
|
|
23
|
+
buildGovernanceConsoleSummaryLines,
|
|
24
|
+
type GovernanceConsoleSnapshot,
|
|
25
|
+
} from '../integrations/lifecycle/cliGovernanceConsole';
|
|
26
|
+
import type { ConsumerPreflightResult } from './framework-menu-consumer-preflight-types';
|
|
22
27
|
|
|
23
28
|
export const formatAdvancedMenuView = (
|
|
24
29
|
actions: ReadonlyArray<MenuAction>,
|
|
25
30
|
options?: {
|
|
26
31
|
evidenceSummary?: FrameworkMenuEvidenceSummary;
|
|
32
|
+
preflight?: ConsumerPreflightResult | null;
|
|
33
|
+
governanceConsole?: GovernanceConsoleSnapshot | null;
|
|
27
34
|
}
|
|
28
35
|
): string => {
|
|
29
36
|
const evidenceSummary = options?.evidenceSummary ?? readEvidenceSummaryForMenu(process.cwd());
|
|
30
37
|
const tokens = buildCliDesignTokens();
|
|
31
38
|
const statusBadge = resolveAdvancedStatusBadge(evidenceSummary, tokens);
|
|
32
39
|
const groupedActions = resolveAdvancedMenuLayout(actions);
|
|
40
|
+
const governanceConsole = options?.preflight
|
|
41
|
+
? {
|
|
42
|
+
governanceObservation: options.preflight.governanceObservation,
|
|
43
|
+
governanceNextAction: options.preflight.governanceNextAction,
|
|
44
|
+
policyValidation: options.preflight.policyValidation,
|
|
45
|
+
experimentalFeatures: options.preflight.experimentalFeatures,
|
|
46
|
+
}
|
|
47
|
+
: (options?.governanceConsole ?? null);
|
|
33
48
|
const lines = [
|
|
34
49
|
'Pumuki Framework Menu (Advanced)',
|
|
35
50
|
`Status: ${statusBadge}`,
|
|
51
|
+
...(governanceConsole
|
|
52
|
+
? [
|
|
53
|
+
'Governance Console',
|
|
54
|
+
...buildGovernanceConsoleSummaryLines({
|
|
55
|
+
governanceObservation: governanceConsole.governanceObservation,
|
|
56
|
+
governanceNextAction: governanceConsole.governanceNextAction,
|
|
57
|
+
policyValidation: governanceConsole.policyValidation,
|
|
58
|
+
experimentalFeatures: governanceConsole.experimentalFeatures,
|
|
59
|
+
}).map((line) => ` ${line}`),
|
|
60
|
+
'',
|
|
61
|
+
]
|
|
62
|
+
: []),
|
|
36
63
|
'C. Switch to consumer menu',
|
|
37
64
|
'',
|
|
38
65
|
...groupedActions.flatMap((group, groupIndex) => [
|
|
@@ -60,11 +87,33 @@ export const formatAdvancedMenuClassicView = (
|
|
|
60
87
|
actions: ReadonlyArray<MenuAction>,
|
|
61
88
|
options?: {
|
|
62
89
|
evidenceSummary?: FrameworkMenuEvidenceSummary;
|
|
90
|
+
preflight?: ConsumerPreflightResult | null;
|
|
91
|
+
governanceConsole?: GovernanceConsoleSnapshot | null;
|
|
63
92
|
}
|
|
64
93
|
): string => {
|
|
65
94
|
const evidenceSummary = options?.evidenceSummary ?? readEvidenceSummaryForMenu(process.cwd());
|
|
95
|
+
const governanceConsole = options?.preflight
|
|
96
|
+
? {
|
|
97
|
+
governanceObservation: options.preflight.governanceObservation,
|
|
98
|
+
governanceNextAction: options.preflight.governanceNextAction,
|
|
99
|
+
policyValidation: options.preflight.policyValidation,
|
|
100
|
+
experimentalFeatures: options.preflight.experimentalFeatures,
|
|
101
|
+
}
|
|
102
|
+
: (options?.governanceConsole ?? null);
|
|
66
103
|
const lines = [
|
|
67
104
|
'Pumuki Framework Menu (Advanced)',
|
|
105
|
+
...(governanceConsole
|
|
106
|
+
? [
|
|
107
|
+
'Governance Console',
|
|
108
|
+
...buildGovernanceConsoleSummaryLines({
|
|
109
|
+
governanceObservation: governanceConsole.governanceObservation,
|
|
110
|
+
governanceNextAction: governanceConsole.governanceNextAction,
|
|
111
|
+
policyValidation: governanceConsole.policyValidation,
|
|
112
|
+
experimentalFeatures: governanceConsole.experimentalFeatures,
|
|
113
|
+
}).map((line) => ` ${line}`),
|
|
114
|
+
'',
|
|
115
|
+
]
|
|
116
|
+
: []),
|
|
68
117
|
'C. Switch to consumer menu',
|
|
69
118
|
...actions.map((action) => {
|
|
70
119
|
const help = ADVANCED_MENU_HELP[action.id];
|