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.
Files changed (77) hide show
  1. package/AGENTS.md +16 -1
  2. package/CHANGELOG.md +9 -0
  3. package/README.md +14 -10
  4. package/VERSION +1 -1
  5. package/core/facts/detectors/text/android.test.ts +2583 -24
  6. package/core/facts/detectors/text/android.ts +4633 -34
  7. package/core/facts/detectors/typescript/index.test.ts +3639 -73
  8. package/core/facts/detectors/typescript/index.ts +4819 -270
  9. package/core/facts/extractHeuristicFacts.ts +271 -6
  10. package/core/rules/presets/heuristics/android.test.ts +314 -1
  11. package/core/rules/presets/heuristics/android.ts +1220 -50
  12. package/core/rules/presets/heuristics/typescript.test.ts +158 -2
  13. package/core/rules/presets/heuristics/typescript.ts +508 -0
  14. package/docs/README.md +3 -3
  15. package/docs/operations/RELEASE_NOTES.md +7 -1
  16. package/docs/operations/framework-menu-consumer-walkthrough.md +18 -15
  17. package/docs/product/API_REFERENCE.md +1 -1
  18. package/docs/product/USAGE.md +1 -1
  19. package/docs/validation/README.md +3 -1
  20. package/integrations/config/skillsCompilerTemplates.test.ts +131 -0
  21. package/integrations/config/skillsCompilerTemplates.ts +953 -7
  22. package/integrations/config/skillsDetectorRegistry.ts +451 -8
  23. package/integrations/config/skillsMarkdownRules.ts +884 -2
  24. package/integrations/evidence/buildEvidence.ts +29 -1
  25. package/integrations/evidence/platformSummary.test.ts +73 -9
  26. package/integrations/evidence/platformSummary.ts +165 -7
  27. package/integrations/evidence/repoState.ts +3 -0
  28. package/integrations/evidence/schema.ts +18 -0
  29. package/integrations/evidence/trackingContract.ts +17 -0
  30. package/integrations/evidence/writeEvidence.test.ts +3 -0
  31. package/integrations/evidence/writeEvidence.ts +29 -1
  32. package/integrations/gate/evaluateAiGate.ts +251 -8
  33. package/integrations/gate/governanceActionCatalog.ts +275 -0
  34. package/integrations/gate/remediationCatalog.ts +8 -0
  35. package/integrations/git/runPlatformGate.ts +9 -1
  36. package/integrations/lifecycle/adapter.ts +24 -0
  37. package/integrations/lifecycle/bootstrapManifest.ts +248 -0
  38. package/integrations/lifecycle/cliGovernanceConsole.ts +69 -0
  39. package/integrations/lifecycle/governanceNextAction.ts +171 -0
  40. package/integrations/lifecycle/governanceObservationSnapshot.ts +369 -0
  41. package/integrations/lifecycle/packageInfo.ts +118 -1
  42. package/integrations/lifecycle/state.ts +8 -1
  43. package/integrations/lifecycle/trackingState.ts +403 -0
  44. package/integrations/lifecycle/watch.ts +1 -1
  45. package/integrations/mcp/aiGateCheck.ts +194 -10
  46. package/integrations/mcp/alignedPlatformGate.ts +232 -0
  47. package/integrations/mcp/enterpriseServer.ts +19 -3
  48. package/integrations/mcp/preFlightCheck.ts +66 -3
  49. package/integrations/mcp/readMcpPrePushStdin.ts +7 -0
  50. package/package.json +1 -1
  51. package/scripts/build-ruralgo-s1-evidence-pack.ts +85 -0
  52. package/scripts/check-tracking-single-active.sh +1 -1
  53. package/scripts/framework-menu-advanced-view-lib.ts +49 -0
  54. package/scripts/framework-menu-consumer-actions-lib.ts +32 -32
  55. package/scripts/framework-menu-consumer-preflight-render.ts +10 -0
  56. package/scripts/framework-menu-consumer-preflight-run.ts +23 -0
  57. package/scripts/framework-menu-consumer-preflight-types.ts +12 -0
  58. package/scripts/framework-menu-consumer-runtime-actions.ts +11 -5
  59. package/scripts/framework-menu-consumer-runtime-audit.ts +0 -28
  60. package/scripts/framework-menu-consumer-runtime-evidence-classic.ts +118 -42
  61. package/scripts/framework-menu-consumer-runtime-lib.ts +38 -0
  62. package/scripts/framework-menu-consumer-runtime-menu.ts +55 -15
  63. package/scripts/framework-menu-consumer-runtime-types.ts +4 -0
  64. package/scripts/framework-menu-evidence-summary-read.ts +17 -1
  65. package/scripts/framework-menu-evidence-summary-types.ts +3 -0
  66. package/scripts/framework-menu-layout-data.ts +3 -23
  67. package/scripts/framework-menu-system-notifications-macos-applescript-dialog.ts +1 -1
  68. package/scripts/framework-menu-system-notifications-macos-dialog-payload.ts +14 -2
  69. package/scripts/framework-menu-system-notifications-macos-swift-source.ts +1 -1
  70. package/scripts/framework-menu-system-notifications-payloads-blocked.ts +128 -4
  71. package/scripts/framework-menu-system-notifications-payloads.ts +8 -1
  72. package/scripts/framework-menu-system-notifications-text.ts +7 -1
  73. package/scripts/framework-menu.ts +37 -2
  74. package/scripts/package-install-smoke-consumer-git-repo-lib.ts +10 -1
  75. package/scripts/package-install-smoke-consumer-npm-lib.ts +46 -9
  76. package/scripts/ruralgo-s1-evidence-pack-lib.ts +200 -0
  77. 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 { runEnterpriseAiGateCheck } from './aiGateCheck';
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 = runEnterpriseAiGateCheck({
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, { status: 'ok' });
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 ${evaluation.violations[0]?.code ?? 'la causa'} y vuelve a ejecutar.`;
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
- : hints[0] ?? 'Corrige la causa bloqueante y vuelve a ejecutar el pre-flight.';
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,
@@ -0,0 +1,7 @@
1
+ export const readMcpPrePushStdin = (): string => {
2
+ const envInput = process.env.PUMUKI_PRE_PUSH_STDIN;
3
+ if (typeof envInput === 'string' && envInput.trim().length > 0) {
4
+ return envInput;
5
+ }
6
+ return '';
7
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pumuki",
3
- "version": "6.3.129",
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];