pumuki 6.3.307 → 6.3.309
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/CHANGELOG.md +6 -0
- package/core/facts/detectors/text/ios.test.ts +621 -0
- package/core/facts/detectors/text/ios.ts +722 -0
- package/core/facts/extractHeuristicFacts.ts +22 -4
- package/core/rules/presets/heuristics/ios.test.ts +83 -1
- package/core/rules/presets/heuristics/ios.ts +329 -0
- package/integrations/config/skillsDetectorRegistry.ts +111 -1
- package/integrations/evidence/buildEvidence.ts +72 -0
- package/integrations/git/aiGateRepoPolicyFindings.ts +2 -1
- package/integrations/lifecycle/adapter.templates.json +50 -1
- package/integrations/lifecycle/doctor.ts +41 -5
- package/integrations/lifecycle/preWriteLease.ts +5 -1
- package/package.json +1 -1
- package/scripts/framework-menu-matrix-canary-evidence.ts +42 -1
- package/scripts/framework-menu-matrix-canary-lib.ts +25 -2
- package/scripts/framework-menu-matrix-canary-scenario.ts +3 -1
- package/scripts/framework-menu-matrix-canary-types.ts +6 -1
- package/scripts/framework-menu-system-notifications-macos-dialog-payload.ts +31 -3
- package/scripts/framework-menu-system-notifications-payloads-blocked.ts +76 -2
- package/scripts/framework-menu-system-notifications-payloads.ts +1 -0
- package/scripts/framework-menu-system-notifications-remediation.ts +97 -2
- package/skills.lock.json +1 -1
|
@@ -20,8 +20,10 @@ const BLOCKED_REMEDIATION_BY_CODE: Readonly<Record<string, string>> = {
|
|
|
20
20
|
EVIDENCE_BRANCH_MISMATCH: 'La evidencia no corresponde a esta rama. Regenera el receipt/evidencia y vuelve a validar.',
|
|
21
21
|
EVIDENCE_REPO_ROOT_MISMATCH: 'Regenera la evidencia desde este repositorio y vuelve a validar.',
|
|
22
22
|
PRE_PUSH_UPSTREAM_MISSING: 'Configura upstream con `git push --set-upstream origin <branch>` y repite PRE_PUSH.',
|
|
23
|
-
SDD_SESSION_MISSING:
|
|
24
|
-
|
|
23
|
+
SDD_SESSION_MISSING:
|
|
24
|
+
'Abre una sesión SDD válida para el change activo (`pumuki sdd session --open --change=<id>`) y reejecuta PRE_WRITE. Agente IA: STOP hasta que exista esa sesión.',
|
|
25
|
+
SDD_SESSION_INVALID:
|
|
26
|
+
'Refresca la sesión SDD activa (`pumuki sdd session --refresh --ttl-minutes=90`) y reejecuta PRE_WRITE. Agente IA: STOP hasta que sea válida.',
|
|
25
27
|
OPENSPEC_MISSING: 'Instala OpenSpec en este repositorio y vuelve a validar el gate.',
|
|
26
28
|
MCP_ENTERPRISE_RECEIPT_MISSING: 'Genera el receipt enterprise de MCP y vuelve a validar.',
|
|
27
29
|
BACKEND_AVOID_EXPLICIT_ANY: 'Sustituye `any` por tipos concretos en backend y relanza el gate.',
|
|
@@ -31,6 +33,10 @@ const BLOCKED_REMEDIATION_BY_CODE: Readonly<Record<string, string>> = {
|
|
|
31
33
|
TRACKING_CANONICAL_SOURCE_CONFLICT: TRACKING_BLOCKED_REMEDIATION,
|
|
32
34
|
ACTIVE_RULE_IDS_EMPTY_FOR_CODE_CHANGES_HIGH:
|
|
33
35
|
'Ejecuta `pumuki policy reconcile --strict --json` y revalida antes de continuar.',
|
|
36
|
+
EVIDENCE_PREWRITE_WORKTREE_WARN:
|
|
37
|
+
'Reduce el worktree pendiente a un slice atómico antes del commit: stagea solo la tarea activa o guarda el resto en stash nombrado, y reejecuta PRE_WRITE.',
|
|
38
|
+
EVIDENCE_PREWRITE_WORKTREE_OVER_LIMIT:
|
|
39
|
+
'El worktree supera el límite permitido: divide cambios por scope en commits atómicos o stashes nombrados antes de continuar.',
|
|
34
40
|
};
|
|
35
41
|
|
|
36
42
|
const BLOCKED_REMEDIATION_MAX_LENGTH_BY_VARIANT: Readonly<Record<BlockedRemediationVariant, number>> = {
|
|
@@ -54,6 +60,81 @@ const normalizeBlockedRemediation = (value: string): string =>
|
|
|
54
60
|
const resolveFallbackRemediation = (causeCode: string): string =>
|
|
55
61
|
BLOCKED_REMEDIATION_BY_CODE[causeCode] ?? GENERIC_BLOCKED_REMEDIATION;
|
|
56
62
|
|
|
63
|
+
const resolveSddSessionCauseCode = (
|
|
64
|
+
event: Extract<PumukiCriticalNotificationEvent, { kind: 'gate.blocked' }>,
|
|
65
|
+
causeCode: string
|
|
66
|
+
): 'SDD_SESSION_MISSING' | 'SDD_SESSION_INVALID' | null => {
|
|
67
|
+
if (causeCode === 'SDD_SESSION_MISSING' || causeCode === 'SDD_SESSION_INVALID') {
|
|
68
|
+
return causeCode;
|
|
69
|
+
}
|
|
70
|
+
const searchable = [
|
|
71
|
+
event.causeMessage,
|
|
72
|
+
event.remediation,
|
|
73
|
+
...(event.blockingCauses ?? []).flatMap((cause) => [
|
|
74
|
+
cause.code,
|
|
75
|
+
cause.ruleId,
|
|
76
|
+
cause.message,
|
|
77
|
+
cause.remediation,
|
|
78
|
+
]),
|
|
79
|
+
]
|
|
80
|
+
.filter((value): value is string => typeof value === 'string')
|
|
81
|
+
.join(' ')
|
|
82
|
+
.toLowerCase();
|
|
83
|
+
if (
|
|
84
|
+
searchable.includes('sdd_session_missing') ||
|
|
85
|
+
searchable.includes('no hay sesión sdd activa') ||
|
|
86
|
+
searchable.includes('no hay sesion sdd activa') ||
|
|
87
|
+
searchable.includes('no active sdd session')
|
|
88
|
+
) {
|
|
89
|
+
return 'SDD_SESSION_MISSING';
|
|
90
|
+
}
|
|
91
|
+
if (
|
|
92
|
+
searchable.includes('sdd_session_invalid') ||
|
|
93
|
+
searchable.includes('sesión sdd actual no es válida') ||
|
|
94
|
+
searchable.includes('sesion sdd actual no es valida') ||
|
|
95
|
+
searchable.includes('invalid sdd session')
|
|
96
|
+
) {
|
|
97
|
+
return 'SDD_SESSION_INVALID';
|
|
98
|
+
}
|
|
99
|
+
return null;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const resolveWorktreeHygieneCauseCode = (
|
|
103
|
+
event: Extract<PumukiCriticalNotificationEvent, { kind: 'gate.blocked' }>,
|
|
104
|
+
causeCode: string
|
|
105
|
+
): 'EVIDENCE_PREWRITE_WORKTREE_WARN' | 'EVIDENCE_PREWRITE_WORKTREE_OVER_LIMIT' | null => {
|
|
106
|
+
if (
|
|
107
|
+
causeCode === 'EVIDENCE_PREWRITE_WORKTREE_WARN' ||
|
|
108
|
+
causeCode === 'EVIDENCE_PREWRITE_WORKTREE_OVER_LIMIT'
|
|
109
|
+
) {
|
|
110
|
+
return causeCode;
|
|
111
|
+
}
|
|
112
|
+
const searchable = [
|
|
113
|
+
event.causeMessage,
|
|
114
|
+
event.remediation,
|
|
115
|
+
...(event.blockingCauses ?? []).flatMap((cause) => [
|
|
116
|
+
cause.code,
|
|
117
|
+
cause.ruleId,
|
|
118
|
+
cause.message,
|
|
119
|
+
cause.remediation,
|
|
120
|
+
]),
|
|
121
|
+
]
|
|
122
|
+
.filter((value): value is string => typeof value === 'string')
|
|
123
|
+
.join(' ')
|
|
124
|
+
.toLowerCase();
|
|
125
|
+
if (searchable.includes('evidence_prewrite_worktree_over_limit')) {
|
|
126
|
+
return 'EVIDENCE_PREWRITE_WORKTREE_OVER_LIMIT';
|
|
127
|
+
}
|
|
128
|
+
if (
|
|
129
|
+
searchable.includes('evidence_prewrite_worktree_warn') ||
|
|
130
|
+
searchable.includes('worktree hygiene warning') ||
|
|
131
|
+
searchable.includes('warn_threshold=')
|
|
132
|
+
) {
|
|
133
|
+
return 'EVIDENCE_PREWRITE_WORKTREE_WARN';
|
|
134
|
+
}
|
|
135
|
+
return null;
|
|
136
|
+
};
|
|
137
|
+
|
|
57
138
|
const isGenericPolicyReconcileRemediation = (message: string): boolean => {
|
|
58
139
|
const normalized = message.toLowerCase();
|
|
59
140
|
return normalized.includes('policy reconcile') && normalized.includes('sdd validate');
|
|
@@ -105,6 +186,20 @@ export const resolveBlockedRemediation = (
|
|
|
105
186
|
): string => {
|
|
106
187
|
const variant = options?.variant ?? 'dialog';
|
|
107
188
|
const maxLength = BLOCKED_REMEDIATION_MAX_LENGTH_BY_VARIANT[variant];
|
|
189
|
+
const sddSessionCauseCode = resolveSddSessionCauseCode(event, causeCode);
|
|
190
|
+
if (sddSessionCauseCode) {
|
|
191
|
+
return truncateNotificationText(
|
|
192
|
+
resolveFallbackRemediation(sddSessionCauseCode),
|
|
193
|
+
maxLength
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
const worktreeHygieneCauseCode = resolveWorktreeHygieneCauseCode(event, causeCode);
|
|
197
|
+
if (worktreeHygieneCauseCode) {
|
|
198
|
+
return truncateNotificationText(
|
|
199
|
+
resolveFallbackRemediation(worktreeHygieneCauseCode),
|
|
200
|
+
maxLength
|
|
201
|
+
);
|
|
202
|
+
}
|
|
108
203
|
const blockingCausesCount = event.blockingCauses?.length ?? 0;
|
|
109
204
|
if (blockingCausesCount > 1) {
|
|
110
205
|
return truncateNotificationText(
|