pumuki 6.3.270 → 6.3.271

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 (33) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/VERSION +1 -1
  3. package/core/facts/detectors/text/android.test.ts +538 -0
  4. package/core/facts/detectors/text/android.ts +436 -0
  5. package/core/facts/detectors/text/ios.test.ts +328 -1
  6. package/core/facts/detectors/text/ios.ts +241 -0
  7. package/core/facts/detectors/typescript/index.test.ts +393 -0
  8. package/core/facts/detectors/typescript/index.ts +316 -0
  9. package/core/facts/extractHeuristicFacts.ts +70 -1
  10. package/core/rules/presets/heuristics/android.test.ts +91 -1
  11. package/core/rules/presets/heuristics/android.ts +360 -0
  12. package/core/rules/presets/heuristics/ios.test.ts +54 -1
  13. package/core/rules/presets/heuristics/ios.ts +243 -2
  14. package/core/rules/presets/heuristics/typescript.test.ts +50 -2
  15. package/core/rules/presets/heuristics/typescript.ts +162 -0
  16. package/docs/operations/RELEASE_NOTES.md +4 -0
  17. package/integrations/config/skillsDetectorRegistry.ts +501 -0
  18. package/integrations/config/skillsRuleClassification.ts +127 -3
  19. package/integrations/git/runPlatformGate.ts +4 -1
  20. package/integrations/lifecycle/preWriteAutomation.ts +1 -0
  21. package/integrations/lifecycle/preWriteLease.ts +41 -4
  22. package/package.json +1 -1
  23. package/scripts/classify-skills-rules.ts +2 -2
  24. package/scripts/framework-menu-consumer-actions-lib.ts +9 -9
  25. package/scripts/framework-menu-consumer-runtime-actions.ts +53 -117
  26. package/scripts/framework-menu-consumer-runtime-audit.ts +66 -0
  27. package/scripts/framework-menu-consumer-runtime-menu.ts +4 -4
  28. package/scripts/framework-menu-gate-lib.ts +86 -1
  29. package/scripts/framework-menu-layout-data.ts +3 -3
  30. package/scripts/framework-menu-legacy-audit-render-sections.ts +6 -0
  31. package/scripts/framework-menu.ts +10 -6
  32. package/scripts/package-install-smoke-consumer-npm-lib.ts +10 -4
  33. package/scripts/package-install-smoke-lifecycle-lib.ts +19 -0
@@ -37,8 +37,8 @@ export const renderConsumerRuntimeClassicMenu = (
37
37
  ): string => {
38
38
  const groupedActions = resolveConsumerMenuLayout(actions);
39
39
  const lines = [
40
- 'PUMUKI — Hook-System (run: npx ast-hooks)',
41
- 'AST Intelligence System Overview',
40
+ 'PUMUKI',
41
+ 'Advanced Project Audit — AST Intelligence & Quality Gate',
42
42
  'A. Switch to advanced menu',
43
43
  '',
44
44
  ...groupedActions.flatMap((group) => [
@@ -68,8 +68,8 @@ export const renderConsumerRuntimeModernMenu = (
68
68
  });
69
69
  const groupedActions = resolveConsumerMenuLayout(params.actions);
70
70
  const lines = [
71
- 'PUMUKI — Hook-System (run: npx ast-hooks)',
72
- 'AST Intelligence System Overview',
71
+ 'PUMUKI',
72
+ 'Advanced Project Audit — AST Intelligence & Quality Gate',
73
73
  `Status: ${renderBadge(menuStatus.label, menuStatus.level, tokens)}`,
74
74
  'A. Switch to advanced menu',
75
75
  '',
@@ -104,6 +104,16 @@ export const runStagedGateSilent = async (): Promise<void> => {
104
104
  await runMenuAuditGate(gateParams);
105
105
  };
106
106
 
107
+ export const runStagedGateSilentWithBlocked = async (): Promise<
108
+ ConsumerRuntimeGateResult | void
109
+ > => {
110
+ const gateParams = buildMenuGateParams({
111
+ stage: 'PRE_COMMIT',
112
+ scope: { kind: 'staged' },
113
+ });
114
+ return await runMenuAuditGateWithBlocked(gateParams);
115
+ };
116
+
107
117
  export const runRepoGateSilent = async (): Promise<void> => {
108
118
  const gateParams = buildMenuGateParams({
109
119
  stage: 'PRE_COMMIT',
@@ -112,6 +122,16 @@ export const runRepoGateSilent = async (): Promise<void> => {
112
122
  await runMenuAuditGate(gateParams);
113
123
  };
114
124
 
125
+ export const runRepoGateSilentWithBlocked = async (): Promise<
126
+ ConsumerRuntimeGateResult | void
127
+ > => {
128
+ const gateParams = buildMenuGateParams({
129
+ stage: 'PRE_COMMIT',
130
+ scope: { kind: 'repo' },
131
+ });
132
+ return await runMenuAuditGateWithBlocked(gateParams);
133
+ };
134
+
115
135
  export const runRepoAndStagedGateSilent = async (): Promise<void> => {
116
136
  const gateParams = buildMenuGateParams({
117
137
  stage: 'PRE_COMMIT',
@@ -120,6 +140,16 @@ export const runRepoAndStagedGateSilent = async (): Promise<void> => {
120
140
  await runMenuAuditGate(gateParams);
121
141
  };
122
142
 
143
+ export const runRepoAndStagedGateSilentWithBlocked = async (): Promise<
144
+ ConsumerRuntimeGateResult | void
145
+ > => {
146
+ const gateParams = buildMenuGateParams({
147
+ stage: 'PRE_COMMIT',
148
+ scope: { kind: 'repoAndStaged' },
149
+ });
150
+ return await runMenuAuditGateWithBlocked(gateParams);
151
+ };
152
+
123
153
  export const runRepoAndStagedPrePushGateSilent = async (): Promise<
124
154
  ConsumerRuntimeGateResult | void
125
155
  > => {
@@ -134,6 +164,16 @@ export const runWorkingTreeGateSilent = async (): Promise<void> => {
134
164
  await runMenuAuditGate(gateParams);
135
165
  };
136
166
 
167
+ export const runWorkingTreeGateSilentWithBlocked = async (): Promise<
168
+ ConsumerRuntimeGateResult | void
169
+ > => {
170
+ const gateParams = buildMenuGateParams({
171
+ stage: 'PRE_COMMIT',
172
+ scope: { kind: 'workingTree' },
173
+ });
174
+ return await runMenuAuditGateWithBlocked(gateParams);
175
+ };
176
+
137
177
  export const runWorkingTreePrePushGateSilent = async (): Promise<void> => {
138
178
  const gateParams = buildMenuGateParams({
139
179
  stage: 'PRE_PUSH',
@@ -142,6 +182,16 @@ export const runWorkingTreePrePushGateSilent = async (): Promise<void> => {
142
182
  await runMenuAuditGate(gateParams);
143
183
  };
144
184
 
185
+ export const runWorkingTreePrePushGateSilentWithBlocked = async (): Promise<
186
+ ConsumerRuntimeGateResult | void
187
+ > => {
188
+ const gateParams = buildMenuGateParams({
189
+ stage: 'PRE_PUSH',
190
+ scope: { kind: 'workingTree' },
191
+ });
192
+ return await runMenuAuditGateWithBlocked(gateParams);
193
+ };
194
+
145
195
  export const runUnstagedGateSilent = async (): Promise<void> => {
146
196
  const gateParams = buildMenuGateParams({
147
197
  stage: 'PRE_COMMIT',
@@ -150,10 +200,29 @@ export const runUnstagedGateSilent = async (): Promise<void> => {
150
200
  await runMenuAuditGate(gateParams);
151
201
  };
152
202
 
203
+ export const runUnstagedGateSilentWithBlocked = async (): Promise<
204
+ ConsumerRuntimeGateResult | void
205
+ > => {
206
+ const gateParams = buildMenuGateParams({
207
+ stage: 'PRE_COMMIT',
208
+ scope: { kind: 'unstaged' },
209
+ });
210
+ return await runMenuAuditGateWithBlocked(gateParams);
211
+ };
212
+
153
213
  const runMenuAuditGate = async (
154
214
  gateParams: ReturnType<typeof buildMenuGateParams>
155
215
  ): Promise<void> => {
156
- await defaultDependencies.runPlatformGate({
216
+ await runMenuAuditGateWithBlocked(gateParams);
217
+ };
218
+
219
+ const runMenuAuditGateWithBlocked = async (
220
+ gateParams: ReturnType<typeof buildMenuGateParams>,
221
+ dependencies: MenuGateDependencies = defaultDependencies
222
+ ): Promise<ConsumerRuntimeGateResult | void> => {
223
+ let blocked: ConsumerRuntimeGateResult['blocked'];
224
+
225
+ await dependencies.runPlatformGate({
157
226
  ...gateParams,
158
227
  auditMode: 'engine',
159
228
  sddDecisionOverride: {
@@ -163,6 +232,19 @@ const runMenuAuditGate = async (
163
232
  },
164
233
  dependencies: {
165
234
  printGateFindings: () => {},
235
+ notifyGateBlocked: (params) => {
236
+ blocked = {
237
+ stage: params.stage,
238
+ totalViolations: params.totalViolations,
239
+ causeCode: params.causeCode,
240
+ causeMessage: params.causeMessage,
241
+ remediation: params.remediation,
242
+ };
243
+ return {
244
+ delivered: false,
245
+ reason: 'menu-silent-capture',
246
+ };
247
+ },
166
248
  evaluatePlatformGateFindings: (params) =>
167
249
  evaluatePlatformGateFindings(params, {
168
250
  loadHeuristicsConfig: () => ({
@@ -172,6 +254,8 @@ const runMenuAuditGate = async (
172
254
  }),
173
255
  },
174
256
  });
257
+
258
+ return blocked ? { blocked } : undefined;
175
259
  };
176
260
 
177
261
  const runRepoAndStagedPrePushGateSilentWithDependencies = async (
@@ -198,5 +282,6 @@ const runRepoAndStagedPrePushGateSilentWithDependencies = async (
198
282
  };
199
283
 
200
284
  export const __testables = {
285
+ runMenuAuditGateWithBlocked,
201
286
  runRepoAndStagedPrePushGateSilentWithDependencies,
202
287
  };
@@ -3,7 +3,7 @@ import type { MenuLayoutGroup } from './framework-menu-layout-types';
3
3
  export const CONSUMER_MENU_LAYOUT: ReadonlyArray<MenuLayoutGroup> = [
4
4
  {
5
5
  key: 'read-only-gates',
6
- title: 'Read-Only Gate Flows',
6
+ title: 'Legacy Audit Flows',
7
7
  itemIds: ['1', '2', '3', '4'],
8
8
  },
9
9
  {
@@ -13,12 +13,12 @@ export const CONSUMER_MENU_LAYOUT: ReadonlyArray<MenuLayoutGroup> = [
13
13
  },
14
14
  {
15
15
  key: 'export',
16
- title: 'Legacy Read-Only Export',
16
+ title: 'Legacy Export',
17
17
  itemIds: ['8'],
18
18
  },
19
19
  {
20
20
  key: 'legacy-read-only-diagnostics',
21
- title: 'Legacy Read-Only Diagnostics',
21
+ title: 'Legacy Diagnostics',
22
22
  itemIds: ['5', '6', '7', '9'],
23
23
  },
24
24
  {
@@ -12,9 +12,15 @@ export const formatLegacyStatusLine = (summary: LegacyAuditSummary): string => {
12
12
  };
13
13
 
14
14
  const formatPlatformBlock = (platform: PlatformSummary): string => {
15
+ const total =
16
+ platform.bySeverity.CRITICAL
17
+ + platform.bySeverity.HIGH
18
+ + platform.bySeverity.MEDIUM
19
+ + platform.bySeverity.LOW;
15
20
  const lines = [
16
21
  `┌ Platform: ${platform.platform}`,
17
22
  `│ ● CRITICAL: ${platform.bySeverity.CRITICAL} ● HIGH: ${platform.bySeverity.HIGH} ● MEDIUM: ${platform.bySeverity.MEDIUM} ● LOW: ${platform.bySeverity.LOW}`,
23
+ `│ TOTAL: ${total}`,
18
24
  `│ Files affected: ${platform.filesAffected}`,
19
25
  '│ Top violations:',
20
26
  ];
@@ -11,12 +11,16 @@ import {
11
11
  runRepoAndStagedGate,
12
12
  runRepoAndStagedGateSilent,
13
13
  runRepoGateSilent,
14
+ runRepoGateSilentWithBlocked,
14
15
  runStagedGate,
15
16
  runStagedGateSilent,
17
+ runStagedGateSilentWithBlocked,
16
18
  runWorkingTreeGateSilent,
19
+ runWorkingTreeGateSilentWithBlocked,
17
20
  runRepoAndStagedPrePushGateSilent,
18
21
  runWorkingTreePrePushGateSilent,
19
- runUnstagedGateSilent,
22
+ runWorkingTreePrePushGateSilentWithBlocked,
23
+ runUnstagedGateSilentWithBlocked,
20
24
  } from './framework-menu-gate-lib';
21
25
  import { createFrameworkMenuPrompts } from './framework-menu-prompts';
22
26
  import { resolveDefaultRangeFrom } from './framework-menu-runners';
@@ -60,12 +64,12 @@ const menu = async (): Promise<void> => {
60
64
  printActiveSkillsBundles,
61
65
  });
62
66
  const consumerRuntime = createConsumerMenuRuntime({
63
- runRepoGate: runRepoGateSilent,
67
+ runRepoGate: runRepoGateSilentWithBlocked,
64
68
  runRepoAndStagedGate: runRepoAndStagedPrePushGateSilent,
65
- runStagedGate: runStagedGateSilent,
66
- runUnstagedGate: runUnstagedGateSilent,
67
- runWorkingTreeGate: runWorkingTreePrePushGateSilent,
68
- runWorkingTreePreCommitGate: runWorkingTreeGateSilent,
69
+ runStagedGate: runStagedGateSilentWithBlocked,
70
+ runUnstagedGate: runUnstagedGateSilentWithBlocked,
71
+ runWorkingTreeGate: runWorkingTreePrePushGateSilentWithBlocked,
72
+ runWorkingTreePreCommitGate: runWorkingTreeGateSilentWithBlocked,
69
73
  write: (text) => {
70
74
  output.write(text);
71
75
  },
@@ -15,10 +15,11 @@ import packageJson from '../package.json';
15
15
  const runNpmStep = (
16
16
  workspace: SmokeWorkspace,
17
17
  args: string[],
18
- context: string
18
+ context: string,
19
+ env?: NodeJS.ProcessEnv
19
20
  ): void => {
20
21
  assertSuccess(
21
- runCommand({ cwd: workspace.consumerRepo, executable: 'npm', args }),
22
+ runCommand({ cwd: workspace.consumerRepo, executable: 'npm', args, env }),
22
23
  context
23
24
  );
24
25
  };
@@ -29,10 +30,15 @@ export const installTarballIntoConsumerRepo = (
29
30
  runNpmStep(workspace, ['init', '-y'], 'npm init');
30
31
  writeFileSync(
31
32
  join(workspace.consumerRepo, '.gitignore'),
32
- 'node_modules/\n.ai_evidence.json\n',
33
+ 'node_modules/\n.ai_evidence.json\n.pumuki/context/\n',
33
34
  'utf8'
34
35
  );
35
- runNpmStep(workspace, ['install', workspace.tarballPath ?? ''], 'npm install <tarball>');
36
+ runNpmStep(
37
+ workspace,
38
+ ['install', workspace.tarballPath ?? ''],
39
+ 'npm install <tarball>',
40
+ { PUMUKI_SKIP_POSTINSTALL: '1' }
41
+ );
36
42
  };
37
43
 
38
44
  export const verifyInstalledPackageCanBeRequired = (
@@ -50,6 +50,25 @@ export const runLifecycleInstallStep = (workspace: SmokeWorkspace): void => {
50
50
  };
51
51
 
52
52
  export const runLifecyclePreWriteStep = (workspace: SmokeWorkspace): void => {
53
+ const contextCommand = resolveConsumerPumukiCommand({
54
+ consumerRepo: workspace.consumerRepo,
55
+ binary: 'pumuki',
56
+ args: ['context', 'init'],
57
+ });
58
+ const contextResult = runCommand({
59
+ cwd: workspace.consumerRepo,
60
+ executable: contextCommand.executable,
61
+ args: contextCommand.args,
62
+ env: {
63
+ PUMUKI_DISABLE_SYSTEM_NOTIFICATIONS: '1',
64
+ PUMUKI_SYSTEM_NOTIFICATIONS: '0',
65
+ PUMUKI_NOTIFICATIONS: '0',
66
+ },
67
+ });
68
+ pushCommandLog(workspace.commandLog, contextResult);
69
+ assertNoFatalOutput(contextResult, 'pumuki context init');
70
+ assertSuccess(contextResult, 'pumuki context init');
71
+
53
72
  const command = resolveConsumerPumukiCommand({
54
73
  consumerRepo: workspace.consumerRepo,
55
74
  binary: 'pumuki-pre-write',