pumuki 6.3.113 → 6.3.115
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 +52 -5
- package/README.md +4 -2
- package/VERSION +1 -1
- package/core/facts/detectors/typescript/index.test.ts +0 -229
- package/core/facts/detectors/typescript/index.ts +0 -278
- package/core/facts/extractHeuristicFacts.ts +0 -4
- package/core/rules/presets/heuristics/typescript.test.ts +1 -21
- package/core/rules/presets/heuristics/typescript.ts +0 -72
- package/docs/README.md +13 -9
- package/docs/codex-skills/backend-enterprise-rules.md +3 -3
- package/docs/operations/RELEASE_NOTES.md +41 -4
- package/docs/product/API_REFERENCE.md +1 -1
- package/docs/product/HOW_IT_WORKS.md +6 -0
- package/docs/product/INSTALLATION.md +1 -1
- package/docs/product/USAGE.md +42 -5
- package/docs/tracking/plan-curso-pumuki-stack-my-architecture.md +100 -44
- package/docs/validation/README.md +6 -3
- package/integrations/config/skillsDetectorRegistry.ts +0 -24
- package/integrations/config/skillsMarkdownRules.ts +0 -57
- package/integrations/evidence/buildEvidence.ts +0 -24
- package/integrations/evidence/repoState.ts +9 -7
- package/integrations/evidence/schema.ts +0 -18
- package/integrations/evidence/writeEvidence.ts +0 -24
- package/integrations/gate/evaluateAiGate.ts +8 -251
- package/integrations/gate/remediationCatalog.ts +0 -8
- package/integrations/git/GitService.ts +44 -5
- package/integrations/git/aiGateRepoPolicyFindings.ts +86 -17
- package/integrations/git/runPlatformGate.ts +1 -9
- package/integrations/git/runPlatformGateFacts.ts +19 -1
- package/integrations/git/runPlatformGateOutput.ts +41 -42
- package/integrations/lifecycle/adapter.templates.json +1 -0
- package/integrations/lifecycle/adapter.ts +0 -24
- package/integrations/lifecycle/audit.ts +101 -0
- package/integrations/lifecycle/cli.ts +120 -99
- package/integrations/lifecycle/cliSdd.ts +4 -26
- package/integrations/lifecycle/doctor.ts +40 -102
- package/integrations/lifecycle/index.ts +2 -0
- package/integrations/lifecycle/install.ts +0 -21
- package/integrations/lifecycle/packageInfo.ts +1 -118
- package/integrations/lifecycle/state.ts +1 -8
- package/integrations/lifecycle/status.ts +40 -59
- package/integrations/lifecycle/watch.ts +1 -1
- package/integrations/mcp/aiGateCheck.ts +10 -194
- package/integrations/mcp/autoExecuteAiStart.ts +116 -92
- package/integrations/mcp/enterpriseServer.ts +7 -23
- package/integrations/mcp/enterpriseStdioServer.cli.ts +4 -31
- package/integrations/mcp/preFlightCheck.ts +5 -67
- package/integrations/platform/detectPlatforms.ts +37 -0
- package/integrations/sdd/policy.ts +28 -20
- package/package.json +1 -1
- 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 -49
- 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 -38
- package/scripts/framework-menu-consumer-runtime-menu.ts +4 -31
- package/scripts/framework-menu-consumer-runtime-types.ts +3 -5
- 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 -3
- 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-text.ts +1 -7
- package/scripts/framework-menu.ts +3 -24
- 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 -17
- 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 -171
- package/integrations/lifecycle/governanceObservationSnapshot.ts +0 -369
- package/integrations/lifecycle/trackingState.ts +0 -403
- 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,248 +0,0 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
|
|
2
|
-
import { dirname, join } from 'node:path'
|
|
3
|
-
import { getPumukiHooksStatus, resolvePumukiHooksDirectory } from './hookManager'
|
|
4
|
-
import { LifecycleGitService, type ILifecycleGitService } from './gitService'
|
|
5
|
-
import {
|
|
6
|
-
readGovernanceObservationSnapshot,
|
|
7
|
-
type GovernanceContractSurface,
|
|
8
|
-
type GovernanceObservationSnapshot,
|
|
9
|
-
} from './governanceObservationSnapshot'
|
|
10
|
-
import { readGovernanceNextAction, type GovernanceNextActionSummary } from './governanceNextAction'
|
|
11
|
-
import { getCurrentPumukiPackageName, getCurrentPumukiVersion } from './packageInfo'
|
|
12
|
-
import { readLifecycleExperimentalFeaturesSnapshot } from './experimentalFeaturesSnapshot'
|
|
13
|
-
import { readLifecyclePolicyValidationSnapshot } from './policyValidationSnapshot'
|
|
14
|
-
import { readLifecycleState } from './state'
|
|
15
|
-
|
|
16
|
-
export const BOOTSTRAP_MANIFEST_RELATIVE_PATH = '.pumuki/bootstrap-manifest.json'
|
|
17
|
-
|
|
18
|
-
type AdapterCommandContract = {
|
|
19
|
-
path: string
|
|
20
|
-
present: boolean
|
|
21
|
-
hooks: {
|
|
22
|
-
pre_write?: string
|
|
23
|
-
pre_commit?: string
|
|
24
|
-
pre_push?: string
|
|
25
|
-
ci?: string
|
|
26
|
-
}
|
|
27
|
-
mcp: {
|
|
28
|
-
enterprise?: string
|
|
29
|
-
evidence?: string
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export type LifecycleBootstrapManifest = {
|
|
34
|
-
schema_version: '1'
|
|
35
|
-
repo_root: string
|
|
36
|
-
package: {
|
|
37
|
-
name: string
|
|
38
|
-
version: string
|
|
39
|
-
}
|
|
40
|
-
lifecycle: {
|
|
41
|
-
installed: boolean
|
|
42
|
-
version: string | null
|
|
43
|
-
installed_at: string | null
|
|
44
|
-
managed_hooks: ReadonlyArray<string>
|
|
45
|
-
openspec_managed_artifacts: ReadonlyArray<string>
|
|
46
|
-
}
|
|
47
|
-
hooks_directory: {
|
|
48
|
-
path: string
|
|
49
|
-
source: 'git-rev-parse' | 'git-config' | 'default'
|
|
50
|
-
}
|
|
51
|
-
hook_status: Record<string, { managed_block_present: boolean; exists: boolean }>
|
|
52
|
-
contract_surface: GovernanceContractSurface
|
|
53
|
-
governance: {
|
|
54
|
-
effective: GovernanceObservationSnapshot['governance_effective']
|
|
55
|
-
attention_codes: ReadonlyArray<string>
|
|
56
|
-
next_action: GovernanceNextActionSummary
|
|
57
|
-
bootstrap_hints: ReadonlyArray<string>
|
|
58
|
-
}
|
|
59
|
-
sdd: {
|
|
60
|
-
effective_mode: GovernanceObservationSnapshot['sdd']['effective_mode']
|
|
61
|
-
experimental_source: string
|
|
62
|
-
session_active: boolean
|
|
63
|
-
session_valid: boolean
|
|
64
|
-
change_id: string | null
|
|
65
|
-
}
|
|
66
|
-
policy_strict: GovernanceObservationSnapshot['policy_strict']
|
|
67
|
-
git: GovernanceObservationSnapshot['git']
|
|
68
|
-
adapter: AdapterCommandContract
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export type LifecycleBootstrapManifestWriteResult = {
|
|
72
|
-
path: string
|
|
73
|
-
changed: boolean
|
|
74
|
-
manifest: LifecycleBootstrapManifest
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const isRecord = (value: unknown): value is Record<string, unknown> =>
|
|
78
|
-
typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
79
|
-
|
|
80
|
-
const readOptionalCommand = (source: unknown): string | undefined => {
|
|
81
|
-
if (!isRecord(source)) {
|
|
82
|
-
return undefined
|
|
83
|
-
}
|
|
84
|
-
const command = source.command
|
|
85
|
-
return typeof command === 'string' && command.trim().length > 0 ? command.trim() : undefined
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const readAdapterCommandContract = (repoRoot: string): AdapterCommandContract => {
|
|
89
|
-
const path = join(repoRoot, '.pumuki', 'adapter.json')
|
|
90
|
-
if (!existsSync(path)) {
|
|
91
|
-
return {
|
|
92
|
-
path: BOOTSTRAP_MANIFEST_RELATIVE_PATH.replace('bootstrap-manifest.json', 'adapter.json'),
|
|
93
|
-
present: false,
|
|
94
|
-
hooks: {},
|
|
95
|
-
mcp: {},
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
try {
|
|
100
|
-
const parsed = JSON.parse(readFileSync(path, 'utf8')) as unknown
|
|
101
|
-
const hooks = isRecord(parsed) && isRecord(parsed.hooks) ? parsed.hooks : {}
|
|
102
|
-
const mcp = isRecord(parsed) && isRecord(parsed.mcp) ? parsed.mcp : {}
|
|
103
|
-
return {
|
|
104
|
-
path: '.pumuki/adapter.json',
|
|
105
|
-
present: true,
|
|
106
|
-
hooks: {
|
|
107
|
-
pre_write: readOptionalCommand(isRecord(hooks) ? hooks.pre_write : undefined),
|
|
108
|
-
pre_commit: readOptionalCommand(isRecord(hooks) ? hooks.pre_commit : undefined),
|
|
109
|
-
pre_push: readOptionalCommand(isRecord(hooks) ? hooks.pre_push : undefined),
|
|
110
|
-
ci: readOptionalCommand(isRecord(hooks) ? hooks.ci : undefined),
|
|
111
|
-
},
|
|
112
|
-
mcp: {
|
|
113
|
-
enterprise: readOptionalCommand(isRecord(mcp) ? mcp.enterprise : undefined),
|
|
114
|
-
evidence: readOptionalCommand(isRecord(mcp) ? mcp.evidence : undefined),
|
|
115
|
-
},
|
|
116
|
-
}
|
|
117
|
-
} catch {
|
|
118
|
-
return {
|
|
119
|
-
path: '.pumuki/adapter.json',
|
|
120
|
-
present: false,
|
|
121
|
-
hooks: {},
|
|
122
|
-
mcp: {},
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
const parseManagedHooks = (raw?: string): string[] => {
|
|
128
|
-
if (typeof raw !== 'string' || raw.trim().length === 0) {
|
|
129
|
-
return []
|
|
130
|
-
}
|
|
131
|
-
return raw
|
|
132
|
-
.split(',')
|
|
133
|
-
.map((value) => value.trim())
|
|
134
|
-
.filter((value) => value.length > 0)
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
const parseManagedArtifacts = (raw?: string): string[] => {
|
|
138
|
-
if (typeof raw !== 'string' || raw.trim().length === 0) {
|
|
139
|
-
return []
|
|
140
|
-
}
|
|
141
|
-
return raw
|
|
142
|
-
.split(',')
|
|
143
|
-
.map((value) => value.trim())
|
|
144
|
-
.filter((value) => value.length > 0)
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
const toHookStatusSummary = (
|
|
148
|
-
hookStatus: ReturnType<typeof getPumukiHooksStatus>
|
|
149
|
-
): Record<string, { managed_block_present: boolean; exists: boolean }> =>
|
|
150
|
-
Object.fromEntries(
|
|
151
|
-
Object.entries(hookStatus).map(([hook, entry]) => [
|
|
152
|
-
hook,
|
|
153
|
-
{
|
|
154
|
-
managed_block_present: entry.managedBlockPresent,
|
|
155
|
-
exists: entry.exists,
|
|
156
|
-
},
|
|
157
|
-
])
|
|
158
|
-
)
|
|
159
|
-
|
|
160
|
-
export const buildLifecycleBootstrapManifest = (params: {
|
|
161
|
-
repoRoot: string
|
|
162
|
-
git?: ILifecycleGitService
|
|
163
|
-
}): LifecycleBootstrapManifest => {
|
|
164
|
-
const git = params.git ?? new LifecycleGitService()
|
|
165
|
-
const repoRoot = git.resolveRepoRoot(params.repoRoot)
|
|
166
|
-
const lifecycleState = readLifecycleState(git, repoRoot)
|
|
167
|
-
const experimentalFeatures = readLifecycleExperimentalFeaturesSnapshot()
|
|
168
|
-
const policyValidation = readLifecyclePolicyValidationSnapshot(repoRoot)
|
|
169
|
-
const governanceObservation = readGovernanceObservationSnapshot({
|
|
170
|
-
repoRoot,
|
|
171
|
-
experimentalFeatures,
|
|
172
|
-
policyValidation,
|
|
173
|
-
git,
|
|
174
|
-
})
|
|
175
|
-
const governanceNextAction = readGovernanceNextAction({
|
|
176
|
-
repoRoot,
|
|
177
|
-
stage: governanceObservation.evidence.snapshot_stage ?? 'PRE_WRITE',
|
|
178
|
-
governanceObservation,
|
|
179
|
-
})
|
|
180
|
-
const hooksDirectory = resolvePumukiHooksDirectory(repoRoot)
|
|
181
|
-
const hookStatus = getPumukiHooksStatus(repoRoot)
|
|
182
|
-
const adapter = readAdapterCommandContract(repoRoot)
|
|
183
|
-
|
|
184
|
-
return {
|
|
185
|
-
schema_version: '1',
|
|
186
|
-
repo_root: repoRoot,
|
|
187
|
-
package: {
|
|
188
|
-
name: getCurrentPumukiPackageName(),
|
|
189
|
-
version: getCurrentPumukiVersion({ repoRoot }),
|
|
190
|
-
},
|
|
191
|
-
lifecycle: {
|
|
192
|
-
installed: lifecycleState.installed === 'true',
|
|
193
|
-
version: typeof lifecycleState.version === 'string' && lifecycleState.version.length > 0
|
|
194
|
-
? lifecycleState.version
|
|
195
|
-
: null,
|
|
196
|
-
installed_at:
|
|
197
|
-
typeof lifecycleState.installedAt === 'string' && lifecycleState.installedAt.length > 0
|
|
198
|
-
? lifecycleState.installedAt
|
|
199
|
-
: null,
|
|
200
|
-
managed_hooks: parseManagedHooks(lifecycleState.hooks),
|
|
201
|
-
openspec_managed_artifacts: parseManagedArtifacts(lifecycleState.openSpecManagedArtifacts),
|
|
202
|
-
},
|
|
203
|
-
hooks_directory: hooksDirectory,
|
|
204
|
-
hook_status: toHookStatusSummary(hookStatus),
|
|
205
|
-
contract_surface: governanceObservation.contract_surface,
|
|
206
|
-
governance: {
|
|
207
|
-
effective: governanceObservation.governance_effective,
|
|
208
|
-
attention_codes: governanceObservation.attention_codes,
|
|
209
|
-
next_action: governanceNextAction,
|
|
210
|
-
bootstrap_hints: governanceObservation.agent_bootstrap_hints,
|
|
211
|
-
},
|
|
212
|
-
sdd: {
|
|
213
|
-
effective_mode: governanceObservation.sdd.effective_mode,
|
|
214
|
-
experimental_source: governanceObservation.sdd.experimental_source,
|
|
215
|
-
session_active: governanceObservation.sdd_session.active,
|
|
216
|
-
session_valid: governanceObservation.sdd_session.valid,
|
|
217
|
-
change_id: governanceObservation.sdd_session.change_id,
|
|
218
|
-
},
|
|
219
|
-
policy_strict: governanceObservation.policy_strict,
|
|
220
|
-
git: governanceObservation.git,
|
|
221
|
-
adapter,
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
const serializeManifest = (manifest: LifecycleBootstrapManifest): string =>
|
|
226
|
-
`${JSON.stringify(manifest, null, 2)}\n`
|
|
227
|
-
|
|
228
|
-
export const writeLifecycleBootstrapManifest = (params: {
|
|
229
|
-
repoRoot: string
|
|
230
|
-
git?: ILifecycleGitService
|
|
231
|
-
}): LifecycleBootstrapManifestWriteResult => {
|
|
232
|
-
const git = params.git ?? new LifecycleGitService()
|
|
233
|
-
const repoRoot = git.resolveRepoRoot(params.repoRoot)
|
|
234
|
-
const path = join(repoRoot, BOOTSTRAP_MANIFEST_RELATIVE_PATH)
|
|
235
|
-
const manifest = buildLifecycleBootstrapManifest({ repoRoot, git })
|
|
236
|
-
const nextContents = serializeManifest(manifest)
|
|
237
|
-
const currentContents = existsSync(path) ? readFileSync(path, 'utf8') : ''
|
|
238
|
-
const changed = currentContents !== nextContents
|
|
239
|
-
if (changed) {
|
|
240
|
-
mkdirSync(dirname(path), { recursive: true })
|
|
241
|
-
writeFileSync(path, nextContents, 'utf8')
|
|
242
|
-
}
|
|
243
|
-
return {
|
|
244
|
-
path,
|
|
245
|
-
changed,
|
|
246
|
-
manifest,
|
|
247
|
-
}
|
|
248
|
-
}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import type { LifecycleExperimentalFeaturesSnapshot } from './experimentalFeaturesSnapshot';
|
|
2
|
-
import type { GovernanceNextActionSummary } from './governanceNextAction';
|
|
3
|
-
import { buildGovernanceNextActionSummaryLines } from './governanceNextAction';
|
|
4
|
-
import type { GovernanceObservationSnapshot } from './governanceObservationSnapshot';
|
|
5
|
-
import { buildGovernanceObservationSummaryLines } from './governanceObservationSnapshot';
|
|
6
|
-
import { writeInfo } from './cliOutputs';
|
|
7
|
-
import type { LifecyclePolicyValidationSnapshot } from './policyValidationSnapshot';
|
|
8
|
-
|
|
9
|
-
export type GovernanceConsoleSnapshot = {
|
|
10
|
-
governanceObservation: GovernanceObservationSnapshot;
|
|
11
|
-
governanceNextAction: GovernanceNextActionSummary;
|
|
12
|
-
policyValidation: LifecyclePolicyValidationSnapshot;
|
|
13
|
-
experimentalFeatures: LifecycleExperimentalFeaturesSnapshot;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
const GOVERNANCE_CONSOLE_FEATURE_ORDER = [
|
|
17
|
-
'analytics',
|
|
18
|
-
'heuristics',
|
|
19
|
-
'learning_context',
|
|
20
|
-
'mcp_enterprise',
|
|
21
|
-
'operational_memory',
|
|
22
|
-
'pre_write',
|
|
23
|
-
'saas_ingestion',
|
|
24
|
-
'sdd',
|
|
25
|
-
] as const;
|
|
26
|
-
|
|
27
|
-
const buildGovernancePolicySummaryLine = (
|
|
28
|
-
policyValidation: LifecyclePolicyValidationSnapshot
|
|
29
|
-
): string =>
|
|
30
|
-
`Policy-as-code: PRE_WRITE=${policyValidation.stages.PRE_WRITE.validationCode ?? 'n/a'} strict=${policyValidation.stages.PRE_WRITE.strict ? 'yes' : 'no'} ` +
|
|
31
|
-
`PRE_COMMIT=${policyValidation.stages.PRE_COMMIT.validationCode ?? 'n/a'} strict=${policyValidation.stages.PRE_COMMIT.strict ? 'yes' : 'no'} ` +
|
|
32
|
-
`PRE_PUSH=${policyValidation.stages.PRE_PUSH.validationCode ?? 'n/a'} strict=${policyValidation.stages.PRE_PUSH.strict ? 'yes' : 'no'} ` +
|
|
33
|
-
`CI=${policyValidation.stages.CI.validationCode ?? 'n/a'} strict=${policyValidation.stages.CI.strict ? 'yes' : 'no'}`;
|
|
34
|
-
|
|
35
|
-
const buildGovernanceExperimentalSummaryLines = (
|
|
36
|
-
experimentalFeatures: LifecycleExperimentalFeaturesSnapshot
|
|
37
|
-
): string[] =>
|
|
38
|
-
GOVERNANCE_CONSOLE_FEATURE_ORDER.map((featureKey) => {
|
|
39
|
-
const feature = experimentalFeatures.features[featureKey];
|
|
40
|
-
return `Experimental: ${featureKey.toUpperCase()}=${feature.mode} source=${feature.source} layer=${feature.layer} blocking=${feature.blocking ? 'yes' : 'no'} env=${feature.activationVariable}`;
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
export const buildGovernanceConsoleSummaryLines = (
|
|
44
|
-
snapshot: GovernanceConsoleSnapshot
|
|
45
|
-
): string[] => {
|
|
46
|
-
const lines = ['Governance truth:'];
|
|
47
|
-
for (const line of buildGovernanceObservationSummaryLines(snapshot.governanceObservation)) {
|
|
48
|
-
lines.push(` ${line}`);
|
|
49
|
-
}
|
|
50
|
-
for (const hint of snapshot.governanceObservation.evidence.human_summary_preview) {
|
|
51
|
-
lines.push(` Evidence hint: ${hint}`);
|
|
52
|
-
}
|
|
53
|
-
lines.push('Governance next action:');
|
|
54
|
-
for (const line of buildGovernanceNextActionSummaryLines(snapshot.governanceNextAction)) {
|
|
55
|
-
lines.push(` ${line}`);
|
|
56
|
-
}
|
|
57
|
-
lines.push(buildGovernancePolicySummaryLine(snapshot.policyValidation));
|
|
58
|
-
lines.push(...buildGovernanceExperimentalSummaryLines(snapshot.experimentalFeatures));
|
|
59
|
-
return lines;
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
export const printGovernanceConsoleHuman = (
|
|
63
|
-
snapshot: GovernanceConsoleSnapshot
|
|
64
|
-
): void => {
|
|
65
|
-
writeInfo('[pumuki] governance console (S1 / shared status-doctor baseline):');
|
|
66
|
-
for (const line of buildGovernanceConsoleSummaryLines(snapshot)) {
|
|
67
|
-
writeInfo(`[pumuki] ${line}`);
|
|
68
|
-
}
|
|
69
|
-
};
|
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
import type { AiGateStage } from '../gate/evaluateAiGate';
|
|
2
|
-
import { resolveGovernanceCatalogAction } from '../gate/governanceActionCatalog';
|
|
3
|
-
import type { GovernanceObservationSnapshot } from './governanceObservationSnapshot';
|
|
4
|
-
import { writeInfo } from './cliOutputs';
|
|
5
|
-
|
|
6
|
-
export type GovernanceNextActionSummary = {
|
|
7
|
-
stage: AiGateStage;
|
|
8
|
-
phase: 'GREEN' | 'RED';
|
|
9
|
-
action: 'proceed' | 'ask';
|
|
10
|
-
confidence_pct: number;
|
|
11
|
-
reason_code: string;
|
|
12
|
-
instruction: string;
|
|
13
|
-
message: string;
|
|
14
|
-
next_action: {
|
|
15
|
-
kind: 'info' | 'run_command';
|
|
16
|
-
message: string;
|
|
17
|
-
command?: string;
|
|
18
|
-
};
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export type GovernanceNextActionReader = (params: {
|
|
22
|
-
repoRoot: string;
|
|
23
|
-
stage?: AiGateStage;
|
|
24
|
-
governanceObservation: GovernanceObservationSnapshot;
|
|
25
|
-
}) => GovernanceNextActionSummary;
|
|
26
|
-
|
|
27
|
-
const POLICY_ATTENTION_CODE_BY_STAGE: Record<AiGateStage, string> = {
|
|
28
|
-
PRE_WRITE: 'POLICY_PRE_WRITE_NOT_STRICT',
|
|
29
|
-
PRE_COMMIT: 'POLICY_PRE_COMMIT_NOT_STRICT',
|
|
30
|
-
PRE_PUSH: 'POLICY_PRE_PUSH_NOT_STRICT',
|
|
31
|
-
CI: 'POLICY_CI_NOT_STRICT',
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
const resolveBlockedAction = (
|
|
35
|
-
snapshot: GovernanceObservationSnapshot,
|
|
36
|
-
stage: AiGateStage
|
|
37
|
-
): GovernanceNextActionSummary => {
|
|
38
|
-
if (snapshot.attention_codes.includes('EVIDENCE_INVALID_OR_CHAIN')) {
|
|
39
|
-
return {
|
|
40
|
-
stage,
|
|
41
|
-
phase: 'RED',
|
|
42
|
-
action: 'ask',
|
|
43
|
-
confidence_pct: 80,
|
|
44
|
-
...resolveGovernanceCatalogAction({ code: 'EVIDENCE_INVALID_OR_CHAIN', stage }),
|
|
45
|
-
message: 'La evidencia actual no es fiable; detén la ejecución automática hasta regenerarla.',
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
if (
|
|
49
|
-
snapshot.attention_codes.includes('AI_GATE_BLOCKED')
|
|
50
|
-
|| snapshot.attention_codes.includes('EVIDENCE_SNAPSHOT_BLOCK')
|
|
51
|
-
) {
|
|
52
|
-
return {
|
|
53
|
-
stage,
|
|
54
|
-
phase: 'RED',
|
|
55
|
-
action: 'ask',
|
|
56
|
-
confidence_pct: 75,
|
|
57
|
-
...resolveGovernanceCatalogAction({ code: 'AI_GATE_BLOCKED', stage }),
|
|
58
|
-
message: 'El gate efectivo sigue bloqueado; Pumuki no debe marcar verde ni dejar continuar.',
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
if (snapshot.attention_codes.includes('SDD_SESSION_INVALID_OR_EXPIRED')) {
|
|
62
|
-
return {
|
|
63
|
-
stage,
|
|
64
|
-
phase: 'RED',
|
|
65
|
-
action: 'ask',
|
|
66
|
-
confidence_pct: 70,
|
|
67
|
-
...resolveGovernanceCatalogAction({ code: 'SDD_SESSION_INVALID_OR_EXPIRED', stage }),
|
|
68
|
-
message: 'Hay una sesión SDD activa pero inválida; eso rompe el loop documental esperado.',
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
if (snapshot.attention_codes.includes('GITFLOW_PROTECTED_BRANCH_CONTEXT')) {
|
|
72
|
-
return {
|
|
73
|
-
stage,
|
|
74
|
-
phase: 'RED',
|
|
75
|
-
action: 'ask',
|
|
76
|
-
confidence_pct: 65,
|
|
77
|
-
...resolveGovernanceCatalogAction({ code: 'GITFLOW_PROTECTED_BRANCH_CONTEXT', stage }),
|
|
78
|
-
message: 'El contexto actual cae sobre una rama protegida; el flujo enterprise no debe continuar ahí.',
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
if (
|
|
82
|
-
snapshot.attention_codes.includes(POLICY_ATTENTION_CODE_BY_STAGE[stage])
|
|
83
|
-
|| snapshot.enterprise_warn_as_block_env
|
|
84
|
-
) {
|
|
85
|
-
return {
|
|
86
|
-
stage,
|
|
87
|
-
phase: 'RED',
|
|
88
|
-
action: 'ask',
|
|
89
|
-
confidence_pct: 60,
|
|
90
|
-
...resolveGovernanceCatalogAction({ code: 'POLICY_STAGE_NOT_STRICT', stage }),
|
|
91
|
-
message: 'La política efectiva todavía no es estricta en todos los stages requeridos.',
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
if (!snapshot.contract_surface.skills_lock_json || !snapshot.contract_surface.skills_sources_json) {
|
|
95
|
-
return {
|
|
96
|
-
stage,
|
|
97
|
-
phase: 'RED',
|
|
98
|
-
action: 'ask',
|
|
99
|
-
confidence_pct: 55,
|
|
100
|
-
...resolveGovernanceCatalogAction({ code: 'SKILLS_CONTRACT_SURFACE_INCOMPLETE', stage }),
|
|
101
|
-
message: 'El contrato de skills todavía no está completamente materializado en el repo.',
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
if (!snapshot.contract_surface.pumuki_adapter_json) {
|
|
105
|
-
return {
|
|
106
|
-
stage,
|
|
107
|
-
phase: 'RED',
|
|
108
|
-
action: 'ask',
|
|
109
|
-
confidence_pct: 50,
|
|
110
|
-
...resolveGovernanceCatalogAction({ code: 'ADAPTER_WIRING_MISSING', stage }),
|
|
111
|
-
message: 'La línea base Git puede operar, pero el wiring adaptador aún no está materializado.',
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
if (snapshot.attention_codes.includes('EVIDENCE_SNAPSHOT_WARN')) {
|
|
115
|
-
return {
|
|
116
|
-
stage,
|
|
117
|
-
phase: 'RED',
|
|
118
|
-
action: 'ask',
|
|
119
|
-
confidence_pct: 50,
|
|
120
|
-
...resolveGovernanceCatalogAction({ code: 'EVIDENCE_SNAPSHOT_WARN', stage }),
|
|
121
|
-
message: 'La evidencia está en WARN; no conviene tratar el repo como completamente verde.',
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
return {
|
|
125
|
-
stage,
|
|
126
|
-
phase: 'RED',
|
|
127
|
-
action: 'ask',
|
|
128
|
-
confidence_pct: 40,
|
|
129
|
-
...resolveGovernanceCatalogAction({ code: 'GOVERNANCE_ATTENTION', stage }),
|
|
130
|
-
message: 'Todavía hay señales de governance no resueltas.',
|
|
131
|
-
};
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
export const readGovernanceNextAction: GovernanceNextActionReader = (params) => {
|
|
135
|
-
const stage = params.stage ?? 'PRE_WRITE';
|
|
136
|
-
const snapshot = params.governanceObservation;
|
|
137
|
-
if (snapshot.governance_effective === 'green') {
|
|
138
|
-
return {
|
|
139
|
-
stage,
|
|
140
|
-
phase: 'GREEN',
|
|
141
|
-
action: 'proceed',
|
|
142
|
-
confidence_pct: 90,
|
|
143
|
-
...resolveGovernanceCatalogAction({ code: 'READY', stage }),
|
|
144
|
-
message: 'Governance efectiva en verde: continúa con la implementación mínima.',
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
return resolveBlockedAction(snapshot, stage);
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
export const buildGovernanceNextActionSummaryLines = (
|
|
151
|
-
snapshot: GovernanceNextActionSummary
|
|
152
|
-
): string[] => {
|
|
153
|
-
const lines = [
|
|
154
|
-
`Next action: stage=${snapshot.stage} phase=${snapshot.phase} action=${snapshot.action} confidence=${snapshot.confidence_pct}% reason=${snapshot.reason_code}`,
|
|
155
|
-
`Instruction: ${snapshot.instruction}`,
|
|
156
|
-
`Action detail: ${snapshot.next_action.message}`,
|
|
157
|
-
];
|
|
158
|
-
if (snapshot.next_action.command) {
|
|
159
|
-
lines.push(`Command: ${snapshot.next_action.command}`);
|
|
160
|
-
}
|
|
161
|
-
return lines;
|
|
162
|
-
};
|
|
163
|
-
|
|
164
|
-
export const printGovernanceNextActionHuman = (
|
|
165
|
-
snapshot: GovernanceNextActionSummary
|
|
166
|
-
): void => {
|
|
167
|
-
writeInfo('[pumuki] governance next action (S1 / governance console baseline):');
|
|
168
|
-
for (const line of buildGovernanceNextActionSummaryLines(snapshot)) {
|
|
169
|
-
writeInfo(`[pumuki] ${line}`);
|
|
170
|
-
}
|
|
171
|
-
};
|