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
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Socket, createServer } from 'node:net';
|
|
2
2
|
import { startEnterpriseMcpServer } from './enterpriseServer';
|
|
3
|
-
import { resolveMcpEnterpriseExperimentalFeature } from '../policy/experimentalFeatures';
|
|
4
3
|
|
|
5
4
|
type JsonRpcId = string | number | null;
|
|
6
5
|
|
|
@@ -99,32 +98,11 @@ const fetchJson = async (url: string, options?: RequestInit): Promise<unknown> =
|
|
|
99
98
|
}
|
|
100
99
|
};
|
|
101
100
|
|
|
102
|
-
type EnterpriseHealthPayload = {
|
|
103
|
-
status?: string;
|
|
104
|
-
repoRoot?: string;
|
|
105
|
-
experimentalFeatures?: {
|
|
106
|
-
mcp_enterprise?: {
|
|
107
|
-
mode?: string;
|
|
108
|
-
};
|
|
109
|
-
};
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
const canReuseEnterpriseHttp = (
|
|
113
|
-
health: EnterpriseHealthPayload,
|
|
114
|
-
repoRoot: string,
|
|
115
|
-
expectedMcpMode: string
|
|
116
|
-
): boolean =>
|
|
117
|
-
health.status === 'ok'
|
|
118
|
-
&& health.repoRoot === repoRoot
|
|
119
|
-
&& health.experimentalFeatures?.mcp_enterprise?.mode === expectedMcpMode;
|
|
120
|
-
|
|
121
101
|
const startOrReuseEnterpriseHttp = async (): Promise<{
|
|
122
102
|
host: string;
|
|
123
103
|
port: number;
|
|
124
104
|
startedByThisProcess: boolean;
|
|
125
105
|
}> => {
|
|
126
|
-
const repoRoot = process.cwd();
|
|
127
|
-
const expectedMcpMode = resolveMcpEnterpriseExperimentalFeature().mode;
|
|
128
106
|
const host = process.env.PUMUKI_ENTERPRISE_MCP_HOST ?? '127.0.0.1';
|
|
129
107
|
const parsedPort = Number.parseInt(process.env.PUMUKI_ENTERPRISE_MCP_PORT ?? '', 10);
|
|
130
108
|
const preferredPort = Number.isFinite(parsedPort) ? parsedPort : 7391;
|
|
@@ -132,8 +110,8 @@ const startOrReuseEnterpriseHttp = async (): Promise<{
|
|
|
132
110
|
|
|
133
111
|
const healthUrl = `http://${host}:${requestedPort}/health`;
|
|
134
112
|
try {
|
|
135
|
-
const health = (await fetchJson(healthUrl)) as
|
|
136
|
-
if (
|
|
113
|
+
const health = (await fetchJson(healthUrl)) as { status?: string };
|
|
114
|
+
if (health.status === 'ok') {
|
|
137
115
|
return {
|
|
138
116
|
host,
|
|
139
117
|
port: requestedPort,
|
|
@@ -141,12 +119,7 @@ const startOrReuseEnterpriseHttp = async (): Promise<{
|
|
|
141
119
|
};
|
|
142
120
|
}
|
|
143
121
|
} catch (error) {
|
|
144
|
-
|
|
145
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
146
|
-
process.stderr.write(
|
|
147
|
-
`[pumuki-mcp-enterprise-stdio] health probe reuse skipped: ${message}\n`
|
|
148
|
-
);
|
|
149
|
-
}
|
|
122
|
+
void error;
|
|
150
123
|
}
|
|
151
124
|
|
|
152
125
|
const portInUse = await isPortInUse(host, requestedPort);
|
|
@@ -154,7 +127,7 @@ const startOrReuseEnterpriseHttp = async (): Promise<{
|
|
|
154
127
|
startEnterpriseMcpServer({
|
|
155
128
|
host,
|
|
156
129
|
port: resolvedPort,
|
|
157
|
-
repoRoot,
|
|
130
|
+
repoRoot: process.cwd(),
|
|
158
131
|
});
|
|
159
132
|
|
|
160
133
|
return {
|
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
resolveGovernanceCatalogAction,
|
|
3
|
-
type GovernanceCatalogNextAction,
|
|
4
|
-
} from '../gate/governanceActionCatalog';
|
|
5
1
|
import { evaluateAiGate, type AiGateStage, type AiGateViolation } from '../gate/evaluateAiGate';
|
|
6
2
|
import { collectWorktreeAtomicSlices } from '../git/worktreeAtomicSlices';
|
|
7
3
|
import { resolveLearningContextExperimentalFeature } from '../policy/experimentalFeatures';
|
|
8
4
|
import { readSddLearningContext, type SddLearningContext } from '../sdd/learningInsights';
|
|
9
5
|
|
|
10
6
|
const ACTIONABLE_HINTS_BY_CODE: Readonly<Record<string, string>> = {
|
|
11
|
-
EVIDENCE_MISSING:
|
|
7
|
+
EVIDENCE_MISSING:
|
|
8
|
+
'Ejecuta una auditoría (1/2/3/4 u opciones de motor 11–14) para regenerar .ai_evidence.json.',
|
|
12
9
|
EVIDENCE_INVALID: 'Regenera .ai_evidence.json desde una opción de auditoría.',
|
|
13
10
|
EVIDENCE_INTEGRITY_MISSING: 'Refresca evidencia para regenerar metadatos de integridad.',
|
|
14
11
|
EVIDENCE_ACTIVE_RULE_IDS_EMPTY_FOR_CODE_CHANGES:
|
|
@@ -42,28 +39,6 @@ const ACTIONABLE_HINTS_BY_CODE: Readonly<Record<string, string>> = {
|
|
|
42
39
|
'Mapea todas las reglas AUTO a detectores AST antes de continuar.',
|
|
43
40
|
EVIDENCE_TIMESTAMP_FUTURE: 'Corrige la hora del sistema y regenera evidencia.',
|
|
44
41
|
GITFLOW_PROTECTED_BRANCH: 'Evita trabajo directo en ramas protegidas (usa feature/*).',
|
|
45
|
-
GITFLOW_BRANCH_NAMING_INVALID:
|
|
46
|
-
'La rama actual no cumple GitFlow. Usa feature/*, bugfix/*, hotfix/*, release/*, chore/*, refactor/* o docs/*.',
|
|
47
|
-
TRACKING_CANONICAL_SOURCE_CONFLICT:
|
|
48
|
-
'AGENTS.md y los README del repo no apuntan a la misma fuente canónica de tracking.',
|
|
49
|
-
TRACKING_CANONICAL_FILE_MISSING:
|
|
50
|
-
'El repo declara un MD de tracking canónico que ahora mismo no existe.',
|
|
51
|
-
TRACKING_CANONICAL_IN_PROGRESS_INVALID:
|
|
52
|
-
'El MD canónico de tracking debe dejar exactamente una task o fase en construcción.',
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
const normalizeGovernanceCatalogCode = (code: string): string => {
|
|
56
|
-
switch (code) {
|
|
57
|
-
case 'EVIDENCE_INVALID':
|
|
58
|
-
case 'EVIDENCE_CHAIN_INVALID':
|
|
59
|
-
return 'EVIDENCE_INVALID_OR_CHAIN';
|
|
60
|
-
case 'GITFLOW_PROTECTED_BRANCH':
|
|
61
|
-
return 'GITFLOW_PROTECTED_BRANCH_CONTEXT';
|
|
62
|
-
case 'GITFLOW_BRANCH_NAMING_INVALID':
|
|
63
|
-
return 'GITFLOW_BRANCH_NAMING_INVALID_CONTEXT';
|
|
64
|
-
default:
|
|
65
|
-
return code;
|
|
66
|
-
}
|
|
67
42
|
};
|
|
68
43
|
|
|
69
44
|
const buildPreFlightHints = (params: {
|
|
@@ -140,8 +115,6 @@ export type EnterprisePreFlightCheckResult = {
|
|
|
140
115
|
phase: 'GREEN' | 'RED';
|
|
141
116
|
message: string;
|
|
142
117
|
instruction: string;
|
|
143
|
-
reason_code: string;
|
|
144
|
-
next_action: GovernanceCatalogNextAction;
|
|
145
118
|
stage: ReturnType<typeof evaluateAiGate>['stage'];
|
|
146
119
|
policy: ReturnType<typeof evaluateAiGate>['policy'];
|
|
147
120
|
violations: ReturnType<typeof evaluateAiGate>['violations'];
|
|
@@ -181,30 +154,13 @@ export const runEnterprisePreFlightCheck = (params: {
|
|
|
181
154
|
upstream: evaluation.repo_state.git.upstream,
|
|
182
155
|
learningContext,
|
|
183
156
|
});
|
|
184
|
-
const firstViolation = evaluation.violations[0];
|
|
185
|
-
const reasonCode = firstViolation?.code ?? 'READY';
|
|
186
|
-
const governanceAction = firstViolation
|
|
187
|
-
? resolveGovernanceCatalogAction({
|
|
188
|
-
code: normalizeGovernanceCatalogCode(firstViolation.code),
|
|
189
|
-
stage: evaluation.stage,
|
|
190
|
-
})
|
|
191
|
-
: resolveGovernanceCatalogAction({
|
|
192
|
-
code: 'READY',
|
|
193
|
-
stage: evaluation.stage,
|
|
194
|
-
});
|
|
195
157
|
const phase: 'GREEN' | 'RED' = evaluation.allowed ? 'GREEN' : 'RED';
|
|
196
158
|
const message = evaluation.allowed
|
|
197
159
|
? '✅ Pre-flight aprobado: puedes continuar con la implementación.'
|
|
198
|
-
: `🔴 Pre-flight bloqueado: corrige ${
|
|
199
|
-
const instruction =
|
|
160
|
+
: `🔴 Pre-flight bloqueado: corrige ${evaluation.violations[0]?.code ?? 'la causa'} y vuelve a ejecutar.`;
|
|
161
|
+
const instruction = evaluation.allowed
|
|
200
162
|
? 'Implementa el cambio mínimo para pasar en verde y vuelve a validar.'
|
|
201
|
-
:
|
|
202
|
-
const nextAction: GovernanceCatalogNextAction = evaluation.allowed
|
|
203
|
-
? {
|
|
204
|
-
kind: 'info',
|
|
205
|
-
message: governanceAction.next_action.message,
|
|
206
|
-
}
|
|
207
|
-
: governanceAction.next_action;
|
|
163
|
+
: hints[0] ?? 'Corrige la causa bloqueante y vuelve a ejecutar el pre-flight.';
|
|
208
164
|
|
|
209
165
|
return {
|
|
210
166
|
tool: 'pre_flight_check',
|
|
@@ -217,8 +173,6 @@ export const runEnterprisePreFlightCheck = (params: {
|
|
|
217
173
|
phase,
|
|
218
174
|
message,
|
|
219
175
|
instruction,
|
|
220
|
-
reason_code: reasonCode,
|
|
221
|
-
next_action: nextAction,
|
|
222
176
|
stage: evaluation.stage,
|
|
223
177
|
policy: evaluation.policy,
|
|
224
178
|
violations: evaluation.violations,
|
|
@@ -51,6 +51,38 @@ const collectFilePaths = (facts: ReadonlyArray<Fact>): string[] => {
|
|
|
51
51
|
.filter((path): path is string => typeof path === 'string');
|
|
52
52
|
};
|
|
53
53
|
|
|
54
|
+
const ALLOWED_PIN_KEYS = new Set(['ios', 'android', 'backend', 'frontend']);
|
|
55
|
+
|
|
56
|
+
const readPinnedPlatformsFromEnv = (): ReadonlySet<keyof DetectedPlatforms> | null => {
|
|
57
|
+
const raw = process.env.PUMUKI_PIN_PLATFORMS?.trim().toLowerCase();
|
|
58
|
+
if (!raw) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
const tokens = raw
|
|
62
|
+
.split(',')
|
|
63
|
+
.map((token) => token.trim())
|
|
64
|
+
.filter((token) => token.length > 0)
|
|
65
|
+
.filter((token) => ALLOWED_PIN_KEYS.has(token)) as Array<keyof DetectedPlatforms>;
|
|
66
|
+
if (tokens.length === 0) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
return new Set(tokens);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const applyPinnedPlatformsFilter = (
|
|
73
|
+
detected: DetectedPlatforms,
|
|
74
|
+
pin: ReadonlySet<keyof DetectedPlatforms>
|
|
75
|
+
): DetectedPlatforms => {
|
|
76
|
+
const next: DetectedPlatforms = {};
|
|
77
|
+
for (const key of pin) {
|
|
78
|
+
const state = detected[key];
|
|
79
|
+
if (state) {
|
|
80
|
+
next[key] = state;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return next;
|
|
84
|
+
};
|
|
85
|
+
|
|
54
86
|
export const detectPlatformsFromFacts = (
|
|
55
87
|
facts: ReadonlyArray<Fact>
|
|
56
88
|
): DetectedPlatforms => {
|
|
@@ -102,5 +134,10 @@ export const detectPlatformsFromFacts = (
|
|
|
102
134
|
};
|
|
103
135
|
}
|
|
104
136
|
|
|
137
|
+
const pin = readPinnedPlatformsFromEnv();
|
|
138
|
+
if (pin && pin.size > 0) {
|
|
139
|
+
return applyPinnedPlatformsFilter(result, pin);
|
|
140
|
+
}
|
|
141
|
+
|
|
105
142
|
return result;
|
|
106
143
|
};
|
|
@@ -40,7 +40,7 @@ type ExperimentalFeatureConfig = {
|
|
|
40
40
|
|
|
41
41
|
const EXPERIMENTAL_FEATURES: Record<ExperimentalFeatureId, ExperimentalFeatureConfig> = {
|
|
42
42
|
pre_write: {
|
|
43
|
-
defaultMode: '
|
|
43
|
+
defaultMode: 'off',
|
|
44
44
|
activationVariable: 'PUMUKI_EXPERIMENTAL_PRE_WRITE',
|
|
45
45
|
legacyActivationVariable: 'PUMUKI_PREWRITE_ENFORCEMENT',
|
|
46
46
|
},
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
|
-
import {
|
|
2
|
+
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
3
3
|
import { basename, dirname, isAbsolute, relative, resolve } from 'node:path';
|
|
4
4
|
import { readEvidenceResult, type EvidenceReadResult } from '../evidence/readEvidence';
|
|
5
5
|
|
|
@@ -15,7 +15,6 @@ export type SddEvidenceScaffoldResult = {
|
|
|
15
15
|
testStatus: SddEvidenceScaffoldTestStatus;
|
|
16
16
|
testOutputPath: string | null;
|
|
17
17
|
fromEvidencePath: string | null;
|
|
18
|
-
traceabilityMarkdownPath: string | null;
|
|
19
18
|
};
|
|
20
19
|
output: {
|
|
21
20
|
path: string;
|
|
@@ -45,13 +44,6 @@ export type SddEvidenceScaffoldResult = {
|
|
|
45
44
|
source: 'pumuki-sdd-evidence';
|
|
46
45
|
stack: 'sdd-evidence-scaffold';
|
|
47
46
|
};
|
|
48
|
-
traceability: {
|
|
49
|
-
required: boolean;
|
|
50
|
-
path: string | null;
|
|
51
|
-
header_present: boolean;
|
|
52
|
-
rows: number;
|
|
53
|
-
status: 'valid';
|
|
54
|
-
};
|
|
55
47
|
// Legacy fields kept for state-sync compatibility in existing consumers.
|
|
56
48
|
scenario_id: string;
|
|
57
49
|
test_run: {
|
|
@@ -73,13 +65,10 @@ export type SddEvidenceScaffoldResult = {
|
|
|
73
65
|
const computeDigest = (value: string): string =>
|
|
74
66
|
`sha256:${createHash('sha256').update(value, 'utf8').digest('hex')}`;
|
|
75
67
|
|
|
76
|
-
const TRACEABILITY_HEADER = '| ARCHIVO | SKILL | REGLA | EVIDENCIA | ESTADO |';
|
|
77
|
-
const TRACEABILITY_CONTRACT_MARKER = 'ARCHIVO | SKILL | REGLA | EVIDENCIA | ESTADO';
|
|
78
|
-
|
|
79
68
|
const resolveRepoBoundPath = (params: {
|
|
80
69
|
repoRoot: string;
|
|
81
70
|
candidatePath: string;
|
|
82
|
-
flagName: '--from-evidence' | '--test-output'
|
|
71
|
+
flagName: '--from-evidence' | '--test-output';
|
|
83
72
|
}): string => {
|
|
84
73
|
const repoRootAbsolute = resolve(params.repoRoot);
|
|
85
74
|
const resolved = isAbsolute(params.candidatePath)
|
|
@@ -152,87 +141,6 @@ const resolveScenarioReference = (scenarioId: string): string => {
|
|
|
152
141
|
return `${normalized}.feature`;
|
|
153
142
|
};
|
|
154
143
|
|
|
155
|
-
const repoRequiresTraceabilityMatrix = (repoRoot: string): boolean => {
|
|
156
|
-
const agentsPath = resolve(repoRoot, 'AGENTS.md');
|
|
157
|
-
if (!existsSync(agentsPath)) {
|
|
158
|
-
return false;
|
|
159
|
-
}
|
|
160
|
-
const contents = readFileSync(agentsPath, 'utf8');
|
|
161
|
-
return (
|
|
162
|
-
contents.includes('Plantilla obligatoria de trazabilidad por turno') ||
|
|
163
|
-
contents.includes(TRACEABILITY_CONTRACT_MARKER)
|
|
164
|
-
);
|
|
165
|
-
};
|
|
166
|
-
|
|
167
|
-
const validateTraceabilityMarkdown = (params: {
|
|
168
|
-
repoRoot: string;
|
|
169
|
-
required: boolean;
|
|
170
|
-
traceabilityMarkdownPath?: string;
|
|
171
|
-
}): {
|
|
172
|
-
path: string | null;
|
|
173
|
-
header_present: boolean;
|
|
174
|
-
rows: number;
|
|
175
|
-
} => {
|
|
176
|
-
if (!params.required) {
|
|
177
|
-
return {
|
|
178
|
-
path: params.traceabilityMarkdownPath?.trim() ? params.traceabilityMarkdownPath.trim() : null,
|
|
179
|
-
header_present: false,
|
|
180
|
-
rows: 0,
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
const candidate = params.traceabilityMarkdownPath?.trim() ?? '';
|
|
184
|
-
if (candidate.length === 0) {
|
|
185
|
-
throw new Error(
|
|
186
|
-
`[pumuki][sdd] evidence requires --traceability-markdown=<path> because this repository declares the contractual traceability matrix (${TRACEABILITY_HEADER}).`
|
|
187
|
-
);
|
|
188
|
-
}
|
|
189
|
-
const absolutePath = resolveRepoBoundPath({
|
|
190
|
-
repoRoot: params.repoRoot,
|
|
191
|
-
candidatePath: candidate,
|
|
192
|
-
flagName: '--traceability-markdown',
|
|
193
|
-
});
|
|
194
|
-
if (!existsSync(absolutePath)) {
|
|
195
|
-
throw new Error(
|
|
196
|
-
`[pumuki][sdd] traceability markdown file does not exist: ${candidate}. Add the contractual matrix and retry.`
|
|
197
|
-
);
|
|
198
|
-
}
|
|
199
|
-
const markdown = readFileSync(absolutePath, 'utf8');
|
|
200
|
-
const lines = markdown.split(/\r?\n/);
|
|
201
|
-
const headerIndex = lines.findIndex((line) => line.trim() === TRACEABILITY_HEADER);
|
|
202
|
-
if (headerIndex < 0) {
|
|
203
|
-
throw new Error(
|
|
204
|
-
`[pumuki][sdd] traceability markdown must include the contractual header ${TRACEABILITY_HEADER}.`
|
|
205
|
-
);
|
|
206
|
-
}
|
|
207
|
-
let rows = 0;
|
|
208
|
-
for (const line of lines.slice(headerIndex + 1)) {
|
|
209
|
-
const trimmed = line.trim();
|
|
210
|
-
if (!trimmed.startsWith('|')) {
|
|
211
|
-
if (rows > 0) {
|
|
212
|
-
break;
|
|
213
|
-
}
|
|
214
|
-
continue;
|
|
215
|
-
}
|
|
216
|
-
if (/^\|\s*-+\s*\|/.test(trimmed)) {
|
|
217
|
-
continue;
|
|
218
|
-
}
|
|
219
|
-
if (trimmed === TRACEABILITY_HEADER) {
|
|
220
|
-
continue;
|
|
221
|
-
}
|
|
222
|
-
rows += 1;
|
|
223
|
-
}
|
|
224
|
-
if (rows === 0) {
|
|
225
|
-
throw new Error(
|
|
226
|
-
'[pumuki][sdd] traceability markdown must include at least one data row under the contractual matrix header.'
|
|
227
|
-
);
|
|
228
|
-
}
|
|
229
|
-
return {
|
|
230
|
-
path: relative(params.repoRoot, absolutePath).split('\\').join('/'),
|
|
231
|
-
header_present: true,
|
|
232
|
-
rows,
|
|
233
|
-
};
|
|
234
|
-
};
|
|
235
|
-
|
|
236
144
|
export const runSddEvidenceScaffold = (params?: {
|
|
237
145
|
repoRoot?: string;
|
|
238
146
|
dryRun?: boolean;
|
|
@@ -241,7 +149,6 @@ export const runSddEvidenceScaffold = (params?: {
|
|
|
241
149
|
testStatus?: SddEvidenceScaffoldTestStatus;
|
|
242
150
|
testOutputPath?: string;
|
|
243
151
|
fromEvidencePath?: string;
|
|
244
|
-
traceabilityMarkdownPath?: string;
|
|
245
152
|
outputPath?: string;
|
|
246
153
|
now?: () => Date;
|
|
247
154
|
evidenceReader?: (repoRoot: string) => EvidenceReadResult;
|
|
@@ -288,12 +195,6 @@ export const runSddEvidenceScaffold = (params?: {
|
|
|
288
195
|
evidenceResult: evidenceReader(repoRoot),
|
|
289
196
|
fromEvidencePath,
|
|
290
197
|
});
|
|
291
|
-
const traceabilityRequired = repoRequiresTraceabilityMatrix(repoRoot);
|
|
292
|
-
const traceability = validateTraceabilityMarkdown({
|
|
293
|
-
repoRoot,
|
|
294
|
-
required: traceabilityRequired,
|
|
295
|
-
traceabilityMarkdownPath: params?.traceabilityMarkdownPath,
|
|
296
|
-
});
|
|
297
198
|
|
|
298
199
|
const now = params?.now ?? (() => new Date());
|
|
299
200
|
const generatedAt = now().toISOString();
|
|
@@ -331,13 +232,6 @@ export const runSddEvidenceScaffold = (params?: {
|
|
|
331
232
|
source: 'pumuki-sdd-evidence',
|
|
332
233
|
stack: 'sdd-evidence-scaffold',
|
|
333
234
|
},
|
|
334
|
-
traceability: {
|
|
335
|
-
required: traceabilityRequired,
|
|
336
|
-
path: traceability.path,
|
|
337
|
-
header_present: traceability.header_present,
|
|
338
|
-
rows: traceability.rows,
|
|
339
|
-
status: 'valid',
|
|
340
|
-
},
|
|
341
235
|
scenario_id: scenarioId,
|
|
342
236
|
test_run: {
|
|
343
237
|
command: testCommand,
|
|
@@ -373,7 +267,6 @@ export const runSddEvidenceScaffold = (params?: {
|
|
|
373
267
|
testStatus,
|
|
374
268
|
testOutputPath,
|
|
375
269
|
fromEvidencePath,
|
|
376
|
-
traceabilityMarkdownPath: traceability.path,
|
|
377
270
|
},
|
|
378
271
|
output: {
|
|
379
272
|
path: outputRelativePath,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pumuki",
|
|
3
|
-
"version": "6.3.
|
|
3
|
+
"version": "6.3.99",
|
|
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": {
|
|
@@ -54,6 +54,8 @@
|
|
|
54
54
|
"test:saas-ingestion": "npx --yes tsx@4.21.0 --test integrations/lifecycle/__tests__/saasIngestionContract.test.ts integrations/lifecycle/__tests__/saasIngestionBuilder.test.ts integrations/lifecycle/__tests__/saasIngestionTransport.test.ts integrations/lifecycle/__tests__/saasIngestionIdempotency.test.ts integrations/lifecycle/__tests__/saasIngestionAuth.test.ts integrations/lifecycle/__tests__/saasIngestionAudit.test.ts integrations/lifecycle/__tests__/saasIngestionMetrics.test.ts integrations/lifecycle/__tests__/saasIngestionGovernance.test.ts integrations/lifecycle/__tests__/saasFederation.test.ts integrations/lifecycle/__tests__/saasEnterpriseAnalytics.test.ts integrations/lifecycle/__tests__/cli.test.ts",
|
|
55
55
|
"test:operational-memory": "npx --yes tsx@4.21.0 --test integrations/lifecycle/__tests__/operationalMemoryContract.test.ts integrations/lifecycle/__tests__/operationalMemorySignals.test.ts integrations/lifecycle/__tests__/operationalMemorySnapshot.test.ts integrations/git/__tests__/runPlatformGate.test.ts integrations/git/__tests__/runPlatformGateEvidence.test.ts integrations/evidence/__tests__/buildEvidence.test.ts integrations/evidence/writeEvidence.test.ts integrations/evidence/generateEvidence.test.ts",
|
|
56
56
|
"test:stage-gates": "npx --yes tsx@4.21.0 --test integrations/config/__tests__/*.test.ts integrations/gate/__tests__/*.test.ts integrations/git/__tests__/*.test.ts integrations/lifecycle/__tests__/*.test.ts integrations/sdd/__tests__/*.test.ts scripts/__tests__/*.test.ts",
|
|
57
|
+
"smoke:pumuki-surface": "npx --yes tsx@4.21.0 scripts/pumuki-full-surface-smoke.ts",
|
|
58
|
+
"smoke:pumuki-surface-installed": "node scripts/pumuki-smoke-installed-wrapper.cjs",
|
|
57
59
|
"test:deterministic": "npm run test:evidence && npm run test:mcp && npm run test:heuristics",
|
|
58
60
|
"ast:refresh": "node bin/pumuki-pre-commit.js",
|
|
59
61
|
"ast:audit": "node bin/pumuki-pre-commit.js",
|
|
@@ -144,12 +146,13 @@
|
|
|
144
146
|
"validation:phase5-escalation:payload": "bash scripts/build-phase5-support-portal-payload.sh",
|
|
145
147
|
"validation:architecture-guardrails": "npx --yes tsx@4.21.0 --test scripts/__tests__/architecture-file-size-guardrails.test.ts",
|
|
146
148
|
"validation:package-manifest": "node --import tsx scripts/check-package-manifest.ts",
|
|
149
|
+
"validation:pumuki-surface-smoke": "npm run -s smoke:pumuki-surface",
|
|
150
|
+
"validation:local-merge-bar": "npm run -s typecheck && npm run -s validation:pumuki-surface-smoke && npm test",
|
|
147
151
|
"validation:package-smoke": "node --import tsx scripts/package-install-smoke.ts --mode=block",
|
|
148
152
|
"validation:package-smoke:minimal": "node --import tsx scripts/package-install-smoke.ts --mode=minimal",
|
|
149
153
|
"validation:lifecycle-smoke": "node --import tsx scripts/package-install-smoke.ts --mode=minimal",
|
|
150
154
|
"validation:contract-suite:enterprise": "node --import tsx scripts/run-enterprise-contract-suite.ts",
|
|
151
155
|
"validation:consumer-matrix-baseline": "node --import tsx scripts/build-consumer-menu-matrix-baseline.ts",
|
|
152
|
-
"validation:ruralgo-s1-evidence-pack": "npx --yes tsx@4.21.0 scripts/build-ruralgo-s1-evidence-pack.ts",
|
|
153
156
|
"validation:c020-benchmark": "node --import tsx scripts/run-c020-benchmark.ts",
|
|
154
157
|
"validation:clean-artifacts": "npx --yes tsx@4.21.0 scripts/clean-validation-artifacts.ts",
|
|
155
158
|
"skills:compile": "npx --yes tsx@4.21.0 scripts/compile-skills-lock.ts",
|
|
@@ -249,6 +252,8 @@
|
|
|
249
252
|
"integrations/telemetry/*.ts",
|
|
250
253
|
"scripts/*.ts",
|
|
251
254
|
"scripts/consumer-postinstall.cjs",
|
|
255
|
+
"scripts/consumer-postinstall-resolve-args.cjs",
|
|
256
|
+
"scripts/pumuki-smoke-installed-wrapper.cjs",
|
|
252
257
|
"scripts/adapters/*.ts",
|
|
253
258
|
"scripts/adapters/*.md",
|
|
254
259
|
"scripts/*.sh",
|
|
@@ -260,10 +265,13 @@
|
|
|
260
265
|
"docs/product/*.md",
|
|
261
266
|
"docs/rule-packs/*.md",
|
|
262
267
|
"docs/validation/*.md",
|
|
268
|
+
"docs/tracking/plan-curso-pumuki-stack-my-architecture.md",
|
|
263
269
|
"assets/**/*",
|
|
264
270
|
"vendor/skills/**/*",
|
|
265
271
|
"index.js",
|
|
266
272
|
"README.md",
|
|
273
|
+
"AGENTS.md",
|
|
274
|
+
"CHANGELOG.md",
|
|
267
275
|
"LICENSE",
|
|
268
276
|
"VERSION",
|
|
269
277
|
"tsconfig.json",
|
|
@@ -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='
|
|
34
|
+
ACTIVE_PATTERN='^- Estado: 🚧'
|
|
35
35
|
else
|
|
36
36
|
ACTIVE_PATTERN='^- 🚧 (`?P[0-9A-Za-z.-]+`?)'
|
|
37
37
|
fi
|
|
@@ -4,10 +4,11 @@ import type {
|
|
|
4
4
|
ConsumerMenuMatrixReport,
|
|
5
5
|
MatrixOptionId,
|
|
6
6
|
} from './framework-menu-matrix-baseline-lib';
|
|
7
|
+
import { MATRIX_MENU_OPTION_IDS } from './framework-menu-matrix-evidence-lib';
|
|
7
8
|
import type { DoctorDeepCheckLayer, LifecycleDoctorReport } from '../integrations/lifecycle/doctor';
|
|
8
9
|
import type { LifecycleStatus } from '../integrations/lifecycle/status';
|
|
9
10
|
|
|
10
|
-
const OPTION_IDS: ReadonlyArray<MatrixOptionId> = [
|
|
11
|
+
const OPTION_IDS: ReadonlyArray<MatrixOptionId> = [...MATRIX_MENU_OPTION_IDS];
|
|
11
12
|
const DOCTOR_LAYERS: ReadonlyArray<DoctorDeepCheckLayer> = [
|
|
12
13
|
'core',
|
|
13
14
|
'operational',
|
|
@@ -51,45 +52,19 @@ export type ConsumerMenuMatrixBaselineSnapshot = {
|
|
|
51
52
|
};
|
|
52
53
|
};
|
|
53
54
|
|
|
55
|
+
const UNKNOWN_OPTION_REPORT = {
|
|
56
|
+
stage: 'UNKNOWN',
|
|
57
|
+
outcome: 'UNKNOWN',
|
|
58
|
+
filesScanned: 0,
|
|
59
|
+
totalViolations: 0,
|
|
60
|
+
diagnosis: 'unknown' as const,
|
|
61
|
+
};
|
|
62
|
+
|
|
54
63
|
const buildEmptyRound = (): ConsumerMenuMatrixReport => {
|
|
55
64
|
return {
|
|
56
|
-
byOption:
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
outcome: 'UNKNOWN',
|
|
60
|
-
filesScanned: 0,
|
|
61
|
-
totalViolations: 0,
|
|
62
|
-
diagnosis: 'unknown',
|
|
63
|
-
},
|
|
64
|
-
'2': {
|
|
65
|
-
stage: 'UNKNOWN',
|
|
66
|
-
outcome: 'UNKNOWN',
|
|
67
|
-
filesScanned: 0,
|
|
68
|
-
totalViolations: 0,
|
|
69
|
-
diagnosis: 'unknown',
|
|
70
|
-
},
|
|
71
|
-
'3': {
|
|
72
|
-
stage: 'UNKNOWN',
|
|
73
|
-
outcome: 'UNKNOWN',
|
|
74
|
-
filesScanned: 0,
|
|
75
|
-
totalViolations: 0,
|
|
76
|
-
diagnosis: 'unknown',
|
|
77
|
-
},
|
|
78
|
-
'4': {
|
|
79
|
-
stage: 'UNKNOWN',
|
|
80
|
-
outcome: 'UNKNOWN',
|
|
81
|
-
filesScanned: 0,
|
|
82
|
-
totalViolations: 0,
|
|
83
|
-
diagnosis: 'unknown',
|
|
84
|
-
},
|
|
85
|
-
'9': {
|
|
86
|
-
stage: 'UNKNOWN',
|
|
87
|
-
outcome: 'UNKNOWN',
|
|
88
|
-
filesScanned: 0,
|
|
89
|
-
totalViolations: 0,
|
|
90
|
-
diagnosis: 'unknown',
|
|
91
|
-
},
|
|
92
|
-
},
|
|
65
|
+
byOption: Object.fromEntries(
|
|
66
|
+
MATRIX_MENU_OPTION_IDS.map((id) => [id, { ...UNKNOWN_OPTION_REPORT }])
|
|
67
|
+
) as ConsumerMenuMatrixReport['byOption'],
|
|
93
68
|
};
|
|
94
69
|
};
|
|
95
70
|
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const KNOWN_MCP_AGENTS = new Set(['cursor', 'codex', 'claude', 'repo']);
|
|
4
|
+
|
|
5
|
+
const normalizeExplicitAgent = (raw) => {
|
|
6
|
+
const trimmed = (raw ?? '').trim();
|
|
7
|
+
if (!trimmed) {
|
|
8
|
+
return '';
|
|
9
|
+
}
|
|
10
|
+
const lower = trimmed.toLowerCase();
|
|
11
|
+
if (lower === '0' || lower === 'none' || lower === 'false') {
|
|
12
|
+
return '';
|
|
13
|
+
}
|
|
14
|
+
if (!KNOWN_MCP_AGENTS.has(lower)) {
|
|
15
|
+
return '';
|
|
16
|
+
}
|
|
17
|
+
return lower;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const resolveConsumerPostinstallInstallExtras = (_consumerRoot, env = process.env) => {
|
|
21
|
+
if (env.PUMUKI_POSTINSTALL_SKIP_MCP === '1') {
|
|
22
|
+
return { extras: [], reason: 'skip_mcp' };
|
|
23
|
+
}
|
|
24
|
+
const withMcpFlag =
|
|
25
|
+
env.PUMUKI_POSTINSTALL_WITH_MCP === '1' ||
|
|
26
|
+
env.PUMUKI_POSTINSTALL_WITH_MCP?.toLowerCase() === 'true';
|
|
27
|
+
const explicit = normalizeExplicitAgent(env.PUMUKI_POSTINSTALL_MCP_AGENT);
|
|
28
|
+
if (explicit) {
|
|
29
|
+
return { extras: ['--with-mcp', `--agent=${explicit}`], reason: 'explicit_agent' };
|
|
30
|
+
}
|
|
31
|
+
if (withMcpFlag) {
|
|
32
|
+
return { extras: ['--with-mcp', '--agent=repo'], reason: 'explicit_repo_flag' };
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
extras: [],
|
|
36
|
+
reason: 'disabled_default',
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
module.exports = {
|
|
41
|
+
KNOWN_MCP_AGENTS,
|
|
42
|
+
resolveConsumerPostinstallInstallExtras,
|
|
43
|
+
normalizeExplicitAgent,
|
|
44
|
+
};
|