pumuki 6.3.278 → 6.3.279

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 CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## [6.3.279] - 2026-05-18
4
+
5
+ - `PUMUKI-INC-149`: `pumuki sdd validate --stage=PRE_WRITE --json` now reports the resolved actionable blocking cause first when `next_action` identifies a concrete remediation. This prevents stale `EVIDENCE_GATE_BLOCKED` symptoms from hiding the real PRE_WRITE cause in JSON, terminal panels and blocked notifications.
6
+
3
7
  ## [6.3.278] - 2026-05-18
4
8
 
5
9
  - `PUMUKI-INC-149`: `EVIDENCE_GATE_BLOCKED` no longer hides the real blocking cause. PRE_WRITE/AI Gate now expands blocked evidence into actionable causes from `snapshot.findings` and `ai_gate.violations`, including rule, code, file, lines and remediation when available, while preserving the PRE_WRITE lease fail-closed contract.
@@ -1992,6 +1992,25 @@ export const resolvePreWriteBlockedRemediation = (params: {
1992
1992
  return PRE_WRITE_HINTS_BY_CODE[params.causeCode] ?? buildPreWriteDefaultRemediation();
1993
1993
  };
1994
1994
 
1995
+ export const prioritizePreWriteAiGateViolations = (
1996
+ aiGate: ReturnType<typeof evaluateAiGate>,
1997
+ nextAction?: PreWriteValidationEnvelope['next_action']
1998
+ ): ReturnType<typeof evaluateAiGate> => {
1999
+ if (!nextAction?.reason) {
2000
+ return aiGate;
2001
+ }
2002
+ const violations = [...aiGate.violations];
2003
+ violations.sort((left, right) => {
2004
+ const leftMatches = left.code === nextAction.reason ? 0 : 1;
2005
+ const rightMatches = right.code === nextAction.reason ? 0 : 1;
2006
+ return leftMatches - rightMatches;
2007
+ });
2008
+ return {
2009
+ ...aiGate,
2010
+ violations,
2011
+ };
2012
+ };
2013
+
1995
2014
  const wrapPreWritePanelLine = (value: string, width: number): string[] => {
1996
2015
  if (width < 20 || value.length <= width) {
1997
2016
  return [value];
@@ -37,6 +37,7 @@ import {
37
37
  buildSddExperimentalEnableAdvisoryCommand,
38
38
  runRawPreWriteAiGateCheck,
39
39
  buildPreWriteExperimentalEnableAdvisoryCommand,
40
+ prioritizePreWriteAiGateViolations,
40
41
  } from './cli';
41
42
 
42
43
  export const runSddCommand = async (parsed: ParsedArgs, activeDependencies: LifecycleCliDependencies): Promise<number> => {
@@ -205,6 +206,10 @@ export const runSddCommand = async (parsed: ParsedArgs, activeDependencies: Life
205
206
  sdd: result,
206
207
  aiGate: rawPreWriteAiGate ?? aiGate,
207
208
  });
209
+ const effectiveAiGate = rawPreWriteAiGate ?? aiGate;
210
+ const reportedAiGate = effectiveAiGate
211
+ ? prioritizePreWriteAiGateViolations(effectiveAiGate, nextAction)
212
+ : null;
208
213
  const sddExperimentalNextAction =
209
214
  !aiGate && result.decision.code === 'SDD_EXPERIMENTAL_DISABLED'
210
215
  ? {
@@ -215,10 +220,10 @@ export const runSddCommand = async (parsed: ParsedArgs, activeDependencies: Life
215
220
  if (parsed.json) {
216
221
  writeInfo(
217
222
  JSON.stringify(
218
- (rawPreWriteAiGate ?? aiGate)
223
+ reportedAiGate
219
224
  ? buildPreWriteValidationEnvelope(
220
225
  result,
221
- rawPreWriteAiGate ?? aiGate!,
226
+ reportedAiGate,
222
227
  preWriteEnforcement,
223
228
  experimentalFeatures,
224
229
  policyValidation,
@@ -272,16 +277,16 @@ export const runSddCommand = async (parsed: ParsedArgs, activeDependencies: Life
272
277
  );
273
278
  }
274
279
  }
275
- if (aiGate) {
280
+ if (reportedAiGate) {
276
281
  writeInfo(buildPreWriteValidationPanel({
277
282
  sdd: result,
278
- aiGate,
283
+ aiGate: reportedAiGate,
279
284
  automation: automationTrace,
280
285
  }));
281
286
  writeInfo(
282
- `[pumuki][ai-gate] stage=${aiGate.stage} status=${aiGate.status} violations=${aiGate.violations.length}`
287
+ `[pumuki][ai-gate] stage=${reportedAiGate.stage} status=${reportedAiGate.status} violations=${reportedAiGate.violations.length}`
283
288
  );
284
- for (const violation of aiGate.violations) {
289
+ for (const violation of reportedAiGate.violations) {
285
290
  writeInfo(
286
291
  withOptionalLocation(
287
292
  `[pumuki][ai-gate] ${violation.code}: ${violation.message}`,
@@ -303,14 +308,14 @@ export const runSddCommand = async (parsed: ParsedArgs, activeDependencies: Life
303
308
  activeDependencies.emitAuditSummaryNotificationFromAiGate({
304
309
  repoRoot: process.cwd(),
305
310
  stage: result.stage,
306
- aiGateResult: aiGate,
311
+ aiGateResult: reportedAiGate ?? aiGate,
307
312
  });
308
313
  }
309
314
  if (!result.decision.allowed && preWriteEnforcement.blocking) {
310
315
  activeDependencies.emitGateBlockedNotification({
311
316
  repoRoot: process.cwd(),
312
317
  stage: result.stage,
313
- totalViolations: aiGate?.violations.length ?? 0,
318
+ totalViolations: reportedAiGate?.violations.length ?? aiGate?.violations.length ?? 0,
314
319
  causeCode: result.decision.code,
315
320
  causeMessage: result.decision.message,
316
321
  remediation: resolvePreWriteBlockedRemediation({
@@ -320,21 +325,21 @@ export const runSddCommand = async (parsed: ParsedArgs, activeDependencies: Life
320
325
  });
321
326
  return 1;
322
327
  }
323
- if (aiGate && !aiGate.allowed && preWriteEnforcement.blocking) {
324
- const firstViolation = aiGate.violations[0];
328
+ if (reportedAiGate && !reportedAiGate.allowed && preWriteEnforcement.blocking) {
329
+ const firstViolation = reportedAiGate.violations[0];
325
330
  const causeCode = firstViolation?.code ?? 'AI_GATE_BLOCKED';
326
331
  const causeMessage = firstViolation?.message ?? 'AI gate blocked PRE_WRITE stage.';
327
332
  activeDependencies.emitGateBlockedNotification({
328
333
  repoRoot: process.cwd(),
329
334
  stage: result.stage,
330
- totalViolations: aiGate.violations.length,
335
+ totalViolations: reportedAiGate.violations.length,
331
336
  causeCode,
332
337
  causeMessage,
333
338
  remediation: resolvePreWriteBlockedRemediation({
334
339
  causeCode,
335
340
  nextAction,
336
341
  }),
337
- blockingCauses: aiGate.violations.map((violation) => ({
342
+ blockingCauses: reportedAiGate.violations.map((violation) => ({
338
343
  code: violation.code,
339
344
  message: violation.message,
340
345
  ruleId: violation.code,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pumuki",
3
- "version": "6.3.278",
3
+ "version": "6.3.279",
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": {