@event4u/agent-config 16.0.0 → 16.1.0
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/.augment-plugin/marketplace.json +3 -3
- package/.augment-plugin/plugin.json +1 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +297 -137
- package/CONTRIBUTING.md +9 -0
- package/README.md +2 -2
- package/dist/agent-src/commands/analyze/inbox.md +26 -0
- package/dist/agent-src/commands/analyze/roadmap-repos.md +27 -0
- package/dist/agent-src/commands/challenge-me/closure.md +178 -0
- package/dist/agent-src/commands/challenge-me.md +9 -2
- package/dist/agent-src/commands/council/default.md +25 -5
- package/dist/agent-src/commands/feature/plan.md +28 -1
- package/dist/agent-src/commands/feature/roadmap.md +28 -1
- package/dist/agent-src/commands/implement-ticket.md +27 -0
- package/dist/agent-src/commands/jira-ticket.md +27 -0
- package/dist/agent-src/commands/pr/create.md +29 -0
- package/dist/agent-src/commands/pr/merge.md +60 -9
- package/dist/agent-src/commands/roadmap/ai-council.md +7 -1
- package/dist/agent-src/commands/roadmap/create.md +74 -27
- package/dist/agent-src/commands/roadmap/materialize.md +27 -0
- package/dist/agent-src/commands/roadmap/process-full.md +123 -18
- package/dist/agent-src/commands/team.md +22 -0
- package/dist/agent-src/contexts/authority/scope-growth-ownership.md +80 -0
- package/dist/agent-src/contexts/communication/rules-auto/user-interaction-mechanics.md +47 -0
- package/dist/agent-src/contexts/execution/auto-orchestration-activation.md +44 -3
- package/dist/agent-src/contexts/execution/autonomy-mechanics.md +15 -15
- package/dist/agent-src/contexts/execution/decision-closure-execution.md +93 -0
- package/dist/agent-src/contexts/execution/fix-loop-ladder.md +108 -0
- package/dist/agent-src/contexts/execution/plan-confidence-gate.md +4 -2
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +75 -6
- package/dist/agent-src/guidelines/agent-infra/active-remediation-mechanics.md +57 -0
- package/dist/agent-src/guidelines/agent-infra/evaluator-independence-mechanics.md +102 -0
- package/dist/agent-src/guidelines/design-fidelity-routing.md +29 -0
- package/dist/agent-src/rules/autonomous-execution.md +15 -8
- package/dist/agent-src/rules/delegation-policy.md +23 -45
- package/dist/agent-src/rules/design-fidelity.md +32 -37
- package/dist/agent-src/rules/evaluator-independence.md +43 -49
- package/dist/agent-src/rules/test-first.md +41 -0
- package/dist/agent-src/skills/accessibility-auditor/data/manifest.json +3 -3
- package/dist/agent-src/skills/ai-council/SKILL.md +11 -3
- package/dist/agent-src/skills/api-design/data/manifest.json +3 -3
- package/dist/agent-src/skills/database/data/manifest.json +4 -4
- package/dist/agent-src/skills/database/data/query-tuning.csv +3 -3
- package/dist/agent-src/skills/design-review/SKILL.md +50 -0
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +14 -4
- package/dist/agent-src/skills/experiment-loop/SKILL.md +31 -1
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +1 -1
- package/dist/agent-src/skills/storybook-workshop/SKILL.md +42 -3
- package/dist/agent-src/skills/threat-modeling/SKILL.md +9 -4
- package/dist/agent-src/skills/threat-modeling/data/manifest.json +4 -4
- package/dist/agent-src/skills/verify-repair-loop/SKILL.md +37 -3
- package/dist/agent-src/templates/agent-settings.md +1 -1
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/roadmaps.md +188 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/backend/_self_fix.ts +62 -2
- package/dist/agent-src/templates/scripts/work_engine/directives/backend/test.ts +1 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +1 -0
- package/dist/cli-delegate/check_update_banner.js +40 -2
- package/dist/cli-delegate/chunk-4E2W63DA.js +335 -0
- package/dist/cli-delegate/chunk-5R7HOLAF.js +99 -0
- package/dist/cli-delegate/{chunk-IVBPRCQO.js → chunk-6KFEC3G7.js} +1 -1
- package/dist/cli-delegate/{chunk-2TAQ2K4V.js → chunk-6KM6ORRY.js} +55 -386
- package/dist/cli-delegate/{chunk-2XY7ILBT.js → chunk-FC75PGJE.js} +42 -2
- package/dist/cli-delegate/{chunk-GYC3VRYN.js → chunk-FXYUYU4N.js} +57 -13
- package/dist/cli-delegate/{chunk-55ACLDUE.js → chunk-GJCBB2UG.js} +168 -10
- package/dist/cli-delegate/{chunk-AK6HODNQ.js → chunk-HDVVGPQW.js} +873 -539
- package/dist/cli-delegate/{chunk-H32DGUJH.js → chunk-P6ZHP5W2.js} +1 -1
- package/dist/cli-delegate/{chunk-57PN4GYJ.js → chunk-RGNIWTEA.js} +1 -1
- package/dist/cli-delegate/chunk-ROYYTEZU.js +39 -0
- package/dist/cli-delegate/{chunk-3FKR64R5.js → chunk-UNCRJBT3.js} +31 -7
- package/dist/cli-delegate/{chunk-2DK2VJWG.js → chunk-WGXTVKCQ.js} +20 -6
- package/dist/cli-delegate/chunk-YDPILCOL.js +152 -0
- package/dist/cli-delegate/cmd_analyze_session.js +1 -1
- package/dist/cli-delegate/cmd_brand_status.js +1 -1
- package/dist/cli-delegate/cmd_conformance.js +90 -56
- package/dist/cli-delegate/cmd_doctor.js +7 -5
- package/dist/cli-delegate/cmd_explain.js +2 -2
- package/dist/cli-delegate/cmd_export.js +9 -7
- package/dist/cli-delegate/cmd_fleet.js +4 -2
- package/dist/cli-delegate/cmd_handoff.js +4 -4
- package/dist/cli-delegate/cmd_mcp_available.js +1 -1
- package/dist/cli-delegate/cmd_migrate.js +2 -2
- package/dist/cli-delegate/cmd_packs_active.js +2 -2
- package/dist/cli-delegate/cmd_preflight.js +4 -2
- package/dist/cli-delegate/cmd_prune.js +10 -8
- package/dist/cli-delegate/cmd_route_audit.js +2 -2
- package/dist/cli-delegate/cmd_route_explain.js +1 -1
- package/dist/cli-delegate/cmd_session_recycle.js +2 -2
- package/dist/cli-delegate/cmd_settings_get.js +28 -2
- package/dist/cli-delegate/cmd_settings_migrate.js +9 -7
- package/dist/cli-delegate/cmd_settings_set.js +1 -1
- package/dist/cli-delegate/cmd_sync.js +10 -8
- package/dist/cli-delegate/cmd_uninstall.js +16 -13
- package/dist/cli-delegate/cmd_update.js +1 -1
- package/dist/cli-delegate/cmd_upgrade.js +1 -1
- package/dist/cli-delegate/cmd_validate.js +12 -10
- package/dist/cli-delegate/cmd_versions.js +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +85 -38
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +4 -4
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +10 -8
- package/dist/discovery/trust-report.md +3 -3
- package/dist/discovery/workspaces.json +8 -6
- package/dist/hooks/dispatch.js +1832 -1007
- package/dist/install/claudeRuleRewrite.js +14 -3
- package/dist/install/conflict.js +60 -10
- package/dist/install/conflictTracker.js +218 -0
- package/dist/install/fsPrimitives.js +54 -0
- package/dist/install/install.mjs +2007 -1481
- package/dist/install/manifestFiles.js +259 -0
- package/dist/install/preflight.js +14 -2
- package/dist/install/preserve.js +157 -0
- package/dist/install/recordedOwnership.js +132 -0
- package/dist/install/txlog.js +11 -2
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +398 -39
- package/dist/router.json +1 -1
- package/dist/scripts/_lib/agent_settings.js +3 -2
- package/dist/scripts/_lib/fs_atomic.js +167 -0
- package/dist/scripts/_lib/installed_tools.js +460 -0
- package/dist/scripts/_lib/lean_projection_mode.js +3 -2
- package/dist/scripts/_lib/settings_renamed_keys.js +78 -0
- package/dist/server/routes/install.js +8 -0
- package/dist/server/routes/wizard.js +9 -3
- package/dist/server/schemas/settings.js +17 -5
- package/dist/shared/missionExecution.js +97 -0
- package/dist/ui/assets/{index-D0jaCRPM.js → index-DH1xc62v.js} +17 -17
- package/dist/ui/index.html +1 -1
- package/docs/MIGRATION.md +103 -0
- package/docs/contracts/settings-classes.md +26 -7
- package/docs/guidelines/agent-infra/active-remediation-mechanics.md +57 -0
- package/docs/guidelines/agent-infra/evaluator-independence-mechanics.md +102 -0
- package/docs/guidelines/design-fidelity-routing.md +29 -0
- package/package.json +1 -1
- package/src/agent-src/templates/scripts/work_engine/directives/backend/_self_fix.ts +62 -2
- package/src/agent-src/templates/scripts/work_engine/directives/backend/test.ts +1 -0
- package/src/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +1 -0
- package/src/config/agent-settings.template.yml +139 -27
- package/src/config/auto-rule-budget.json +16 -0
- package/src/config/ci-local-parity.yml +18 -5
- package/src/config/continuity-surface.json +21 -0
- package/src/config/gate-coverage.yml +146 -13
- package/src/config/gate-violation-baselines.json +6 -6
- package/src/config/hook-token-budget.json +2 -0
- package/src/config/loop-surfaces.yaml +215 -0
- package/src/config/platform-anchor.json +3 -2
- package/src/config/release-gate-locality.yml +11 -0
- package/src/config/routing-coverage-seed.json +18 -4
- package/src/config/rule-enforcement-baseline.json +0 -1
- package/src/install/claudeRuleRewrite.ts +16 -2
- package/src/install/conflict.ts +65 -9
- package/src/install/conflictTracker.ts +299 -0
- package/src/install/fsPrimitives.ts +54 -0
- package/src/install/manifestFiles.ts +312 -0
- package/src/install/preflight.ts +16 -2
- package/src/install/preserve.ts +205 -0
- package/src/install/recordedOwnership.ts +149 -0
- package/src/install/txlog.ts +11 -2
- package/src/install/types.ts +19 -4
- package/src/scripts/_cli/cmd_conformance.ts +88 -15
- package/src/scripts/_cli/cmd_doctor.ts +4 -3
- package/src/scripts/_cli/cmd_route_explain.ts +9 -2
- package/src/scripts/_cli/cmd_settings_get.ts +44 -0
- package/src/scripts/_cli/doctor_execution.ts +90 -0
- package/src/scripts/_lib/activation_payload.ts +247 -0
- package/src/scripts/_lib/agent_settings.ts +4 -2
- package/src/scripts/_lib/authority_path.ts +102 -0
- package/src/scripts/_lib/cascade_base.ts +94 -0
- package/src/scripts/_lib/changelog_eras.ts +7 -2
- package/src/scripts/_lib/continuation_ladder.ts +149 -2
- package/src/scripts/_lib/council_transport.ts +129 -0
- package/src/scripts/_lib/delivery_ready.ts +112 -0
- package/src/scripts/_lib/forge_protection.ts +267 -0
- package/src/scripts/_lib/hook_platform_keys.ts +27 -0
- package/src/scripts/_lib/json_python_parity.ts +127 -0
- package/src/scripts/_lib/lean_projection_mode.ts +14 -3
- package/src/scripts/_lib/loop_surfaces.ts +382 -0
- package/src/scripts/_lib/mission_record.ts +190 -0
- package/src/scripts/_lib/obligation_frequency.ts +217 -0
- package/src/scripts/_lib/obligations.ts +402 -0
- package/src/scripts/_lib/orchestration_record.ts +11 -20
- package/src/scripts/_lib/release_highlights.ts +199 -10
- package/src/scripts/_lib/release_holds.ts +493 -0
- package/src/scripts/_lib/release_migration_gate.ts +184 -0
- package/src/scripts/_lib/rides_along.ts +102 -0
- package/src/scripts/_lib/settings_renamed_keys.ts +82 -0
- package/src/scripts/_lib/test_delta.ts +166 -0
- package/src/scripts/_lib/test_provenance.ts +171 -0
- package/src/scripts/_lib/typed_op_grant.ts +246 -0
- package/src/scripts/_lib/typed_op_watch.ts +185 -0
- package/src/scripts/ai_council/config.ts +8 -11
- package/src/scripts/ai_council/fallback_config.ts +5 -3
- package/src/scripts/ai_council/ownership_classes.ts +118 -0
- package/src/scripts/ask_block_census.ts +285 -15
- package/src/scripts/check_enforcement_matrix.ts +624 -0
- package/src/scripts/check_gate_reachability.ts +173 -10
- package/src/scripts/check_generator_sync.ts +954 -0
- package/src/scripts/check_preamble_payload_budget.ts +75 -2
- package/src/scripts/check_release_highlights.ts +33 -1
- package/src/scripts/check_release_holds.ts +567 -0
- package/src/scripts/check_rule_projection_integrity.ts +22 -12
- package/src/scripts/check_test_delta.ts +294 -0
- package/src/scripts/check_test_weakening.ts +299 -0
- package/src/scripts/closure_scan.ts +333 -0
- package/src/scripts/compile_hook_manifest.ts +43 -3
- package/src/scripts/council_record_shape.ts +209 -0
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +88 -9
- package/src/scripts/hooks/concern_registry.ts +4 -0
- package/src/scripts/hooks/design_pass_hook.ts +128 -3
- package/src/scripts/hooks/evidence_independence.ts +96 -0
- package/src/scripts/hooks/memory_recall_hook.ts +540 -0
- package/src/scripts/hooks/obligation_settle_hook.ts +182 -0
- package/src/scripts/hooks/rule_inject_hook.ts +49 -1
- package/src/scripts/hooks/run_continuation_hook.ts +17 -20
- package/src/scripts/hooks_doctor.ts +85 -0
- package/src/scripts/hooks_status.ts +19 -0
- package/src/scripts/install.ts +106 -206
- package/src/scripts/janitor.ts +7 -0
- package/src/scripts/lint_decision_classes.ts +464 -0
- package/src/scripts/lint_hook_manifest.ts +11 -0
- package/src/scripts/lint_major_migration_sections.ts +450 -0
- package/src/scripts/lint_plan_risk_register.ts +47 -3
- package/src/scripts/lint_roadmap_blockers.ts +61 -0
- package/src/scripts/lint_roadmap_producers.ts +202 -0
- package/src/scripts/measure_rule_budget.ts +101 -5
- package/src/scripts/new_roadmap.ts +37 -0
- package/src/scripts/orchestration_record.ts +0 -5
- package/src/scripts/release.ts +14 -98
- package/src/scripts/release_drill.ts +267 -1
- package/src/scripts/release_publication.ts +51 -0
- package/src/scripts/report_enforcement_drift.ts +566 -0
- package/src/scripts/report_host_injection_effect.ts +3 -11
- package/src/scripts/report_standing_payload_by_host.ts +26 -152
- package/src/scripts/schemas/agent-settings.schema.json +23 -0
- package/src/scripts/schemas/command.schema.json +4 -0
- package/src/scripts/scope_growth.ts +219 -0
- package/src/scripts/trigger_eval_grandfather.json +0 -1
- package/src/scripts/ui_conformance_probe.ts +622 -0
- package/src/server/schemas/settings.ts +31 -7
- package/src/shared/missionExecution.ts +126 -0
- package/dist/cli-delegate/chunk-523HCFYO.js +0 -90
|
@@ -59,8 +59,6 @@ export type LinePhase = 'refine' | 'memory' | 'analyze' | 'plan' | 'implement' |
|
|
|
59
59
|
* table can be checked against it (`road-to-experience-loop-broadening` 1.3).
|
|
60
60
|
*/
|
|
61
61
|
export type LineOutcome = PhaseOutcome;
|
|
62
|
-
/** Which capsule-emission trigger arm fired first (Phase 1 shadow comparison). */
|
|
63
|
-
export type TriggerArm = 'watermark' | 'saturation' | 'tie';
|
|
64
62
|
/** The orchestration form the form-gate selected (road-to-opt-subagent-harvest P2). */
|
|
65
63
|
export type DispatchModeId =
|
|
66
64
|
| 'do-and-judge'
|
|
@@ -225,12 +223,16 @@ export interface RecordInput {
|
|
|
225
223
|
capsule_emitted?: boolean | undefined;
|
|
226
224
|
/** Total entries across the capsule's arrays — a size proxy, never content. */
|
|
227
225
|
capsule_entries?: number | null | undefined;
|
|
228
|
-
|
|
229
|
-
watermark_step
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
226
|
+
// The three trigger-comparison fields that used to sit here —
|
|
227
|
+
// `watermark_step`, `saturation_step`, `trigger_arm_earlier` — were removed
|
|
228
|
+
// on 2026-09-13. They were accepted by the CLI and no caller could ever
|
|
229
|
+
// compute them: `capsule_trigger.compareTriggers` needs per-step token
|
|
230
|
+
// counts AND per-step surfaced terms, and no payload this tree has observed
|
|
231
|
+
// carries either. `subagent_ledger_hook.ts` names that gap and refuses to
|
|
232
|
+
// invent a proxy, citing this exact module. A flag nothing can fill is the
|
|
233
|
+
// same built-and-unreachable class the rest of this change detects, so it
|
|
234
|
+
// goes rather than waiting behind a label. Re-adding them is one commit
|
|
235
|
+
// once an observation source exists.
|
|
234
236
|
// Audit-log envelope (sensible defaults for a dispatch record)
|
|
235
237
|
phase?: LinePhase | undefined;
|
|
236
238
|
outcome?: LineOutcome | undefined;
|
|
@@ -258,7 +260,6 @@ const BANDS: readonly Band[] = ['low', 'medium', 'high'];
|
|
|
258
260
|
const PHASES: readonly LinePhase[] = ['refine', 'memory', 'analyze', 'plan', 'implement', 'test', 'verify', 'report'];
|
|
259
261
|
const LOOKUP_CLASSES: readonly LookupClass[] = ['definition', 'references', 'string-existence', 'report-run'];
|
|
260
262
|
const ROUTES_TAKEN: readonly RouteTaken[] = ['primitive', 'subagent', 'ask'];
|
|
261
|
-
const TRIGGER_ARMS: readonly TriggerArm[] = ['watermark', 'saturation', 'tie'];
|
|
262
263
|
/** Hex-only payload hash — a hash can never smuggle content (privacy by construction). */
|
|
263
264
|
const PAYLOAD_HASH_RE = /^[a-f0-9]{8,64}$/i;
|
|
264
265
|
/** Id-shaped origin tag — enum-ish, never free-form prose. */
|
|
@@ -549,16 +550,9 @@ export function buildOrchestrationLine(input: RecordInput): BuiltLine {
|
|
|
549
550
|
if (input.capsule_emitted !== undefined && typeof input.capsule_emitted !== 'boolean') {
|
|
550
551
|
errors.push('capsule_emitted must be a boolean or omitted');
|
|
551
552
|
}
|
|
552
|
-
for (const [key, v] of [
|
|
553
|
-
['capsule_entries', input.capsule_entries],
|
|
554
|
-
['watermark_step', input.watermark_step],
|
|
555
|
-
['saturation_step', input.saturation_step],
|
|
556
|
-
] as const) {
|
|
553
|
+
for (const [key, v] of [['capsule_entries', input.capsule_entries]] as const) {
|
|
557
554
|
if (v != null && (!isInt(v) || v < 0)) errors.push(`${key} must be a non-negative integer count`);
|
|
558
555
|
}
|
|
559
|
-
if (input.trigger_arm_earlier != null && !TRIGGER_ARMS.includes(input.trigger_arm_earlier)) {
|
|
560
|
-
errors.push(`trigger_arm_earlier must be one of ${TRIGGER_ARMS.join(' | ')} (or omitted / null when neither arm fired)`);
|
|
561
|
-
}
|
|
562
556
|
|
|
563
557
|
for (const [key, v] of [
|
|
564
558
|
['model_requested', input.model_requested],
|
|
@@ -619,9 +613,6 @@ export function buildOrchestrationLine(input: RecordInput): BuiltLine {
|
|
|
619
613
|
// capsule shadow-measurement — readers ignore unknowns per audit-log-v1
|
|
620
614
|
capsule_emitted: input.capsule_emitted ?? null,
|
|
621
615
|
capsule_entries: input.capsule_entries ?? null,
|
|
622
|
-
watermark_step: input.watermark_step ?? null,
|
|
623
|
-
saturation_step: input.saturation_step ?? null,
|
|
624
|
-
trigger_arm_earlier: input.trigger_arm_earlier ?? null,
|
|
625
616
|
};
|
|
626
617
|
|
|
627
618
|
const line: Record<string, unknown> = {
|
|
@@ -77,6 +77,21 @@ export interface SpanCommit {
|
|
|
77
77
|
breaking: boolean;
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
/**
|
|
81
|
+
* Optional inputs the derivation cannot get from the span alone.
|
|
82
|
+
*
|
|
83
|
+
* `readTouchedFile` is the one seam where a label needs FILE CONTENT rather
|
|
84
|
+
* than commit metadata, and it is a callback rather than a git call inside the
|
|
85
|
+
* derivation for two reasons: the derivation stays pure and unit-testable
|
|
86
|
+
* against a fixture map, and the caller keeps ownership of WHICH ref it is
|
|
87
|
+
* reading (the gate reads `--to`, the generator reads `HEAD`). Returning
|
|
88
|
+
* `null` means "not readable" and is never treated as "no residual" — an
|
|
89
|
+
* unreadable file simply does not substantiate the label.
|
|
90
|
+
*/
|
|
91
|
+
export interface DeriveOptions {
|
|
92
|
+
readTouchedFile?: (path: string) => string | null;
|
|
93
|
+
}
|
|
94
|
+
|
|
80
95
|
/** One derived hit: the commit that substantiates a label. */
|
|
81
96
|
export interface CategoryHit {
|
|
82
97
|
sha: string;
|
|
@@ -122,15 +137,18 @@ const _EXECUTABLE_EXACT: ReadonlySet<string> = new Set([
|
|
|
122
137
|
'src/scripts/agent-config',
|
|
123
138
|
]);
|
|
124
139
|
|
|
125
|
-
function
|
|
126
|
-
return
|
|
127
|
-
(
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
_EXECUTABLE_PREFIXES.some((p) => f.path.startsWith(p)),
|
|
140
|
+
function _is_executable_path(p: string): boolean {
|
|
141
|
+
return (
|
|
142
|
+
_EXECUTABLE_SUFFIX.test(p) ||
|
|
143
|
+
_EXECUTABLE_EXACT.has(p) ||
|
|
144
|
+
_EXECUTABLE_PREFIXES.some((prefix) => p.startsWith(prefix))
|
|
131
145
|
);
|
|
132
146
|
}
|
|
133
147
|
|
|
148
|
+
function _touches_executable(files: SpanCommit['files']): boolean {
|
|
149
|
+
return files.some((f) => _is_executable_path(f.path));
|
|
150
|
+
}
|
|
151
|
+
|
|
134
152
|
/**
|
|
135
153
|
* Conventional-commit type, lower-cased, or `''` when the subject carries no
|
|
136
154
|
* conventional prefix.
|
|
@@ -179,15 +197,67 @@ const _NULL_FORMS: readonly RegExp[] = [
|
|
|
179
197
|
/\bon (?:its|the) own falsifier\b/iu,
|
|
180
198
|
];
|
|
181
199
|
|
|
200
|
+
/**
|
|
201
|
+
* Self-declared-residual forms — the `Known limitations` half of the same
|
|
202
|
+
* shape `_NULL_FORMS` uses, and taken from real prose in this tree rather than
|
|
203
|
+
* invented.
|
|
204
|
+
*
|
|
205
|
+
* PHRASE-LEVEL, NEVER WORD-LEVEL, and that is the measured part. The first
|
|
206
|
+
* draft matched the bare word `residual`, and over `15.0.0..16.0.0` its top
|
|
207
|
+
* hit was a commit where `residual` is a LOCAL VARIABLE holding a parse error
|
|
208
|
+
* (`const residual = residualParseError(rawText)`). A residual in this repo's
|
|
209
|
+
* vocabulary is a sentence about what a change did not reach, so every pattern
|
|
210
|
+
* below carries the noun it qualifies or the verb that declares it.
|
|
211
|
+
*
|
|
212
|
+
* TWO FURTHER NARROWINGS, both taken from running this derivation over the
|
|
213
|
+
* `14.23.0..15.0.0` and `15.0.0..16.0.0` spans before it gated anything, and
|
|
214
|
+
* both the same failure as the bare word — the pattern matching the repo's
|
|
215
|
+
* VOCABULARY for limits rather than a declaration of one:
|
|
216
|
+
*
|
|
217
|
+
* · `residual risk` / `residual cost` are OUT; `residual limit` / `residual
|
|
218
|
+
* gap` are in. "carries more residual risk than one just past the fire
|
|
219
|
+
* threshold" (`review_skipped_record.ts`) is a threshold rationale, and it
|
|
220
|
+
* alone produced three of the five candidates over `15.0.0..16.0.0`.
|
|
221
|
+
* · `known limitation(s)` is in; bare `known limit(s)` is OUT, because
|
|
222
|
+
* `build_proof.ts` EMITS a report section called `## 3. Known limits` —
|
|
223
|
+
* the phrase is a string literal in a generator, not a limit the file has.
|
|
224
|
+
*
|
|
225
|
+
* `does not yet` and `is not covered` are the two broadest and they are kept:
|
|
226
|
+
* both are the plainest way this tree writes a residual down, and the second
|
|
227
|
+
* is what makes `obligation_frequency.ts`'s "one session is not covered by a
|
|
228
|
+
* `session_start` check" derivable — a true positive neither narrow pattern
|
|
229
|
+
* would have reached.
|
|
230
|
+
*/
|
|
231
|
+
const _RESIDUAL_FORMS: readonly RegExp[] = [
|
|
232
|
+
/\bknown limitations?\b/iu,
|
|
233
|
+
/\bknown false[- ]positive/iu,
|
|
234
|
+
/\bresidual (?:limit|gap)\b/iu,
|
|
235
|
+
/\bowes? (?:its|their|the) residual\b/iu,
|
|
236
|
+
/\b(?:limit|gap|residual|recall limit) that remains\b/iu,
|
|
237
|
+
/\bdoes not yet\b/iu,
|
|
238
|
+
/\b(?:is|are|was|were) not covered\b/iu,
|
|
239
|
+
/\bnot (?:excluded|covered) and tested\b/iu,
|
|
240
|
+
/\bnamed rather than left to be discovered\b/iu,
|
|
241
|
+
/\bnot gate-checkable\b/iu,
|
|
242
|
+
];
|
|
243
|
+
|
|
182
244
|
/**
|
|
183
245
|
* Why a label fired, in generator-facing prose. Keyed by label; a label absent
|
|
184
|
-
* here is never derived
|
|
246
|
+
* here is never derived.
|
|
247
|
+
*
|
|
248
|
+
* All FIVE labels are keyed here since 2026-09-13. `Known limitations` used to
|
|
249
|
+
* be the exception — "pure prose, not checkable" — and the consequence is what
|
|
250
|
+
* removed it: the field printed `_none_` in 15.0.0 and in 16.0.0, both times
|
|
251
|
+
* over a span whose own code documented its residuals, because `_none_` is
|
|
252
|
+
* what an underived label prints when nobody writes anything. A derived
|
|
253
|
+
* `_none_` and an unfilled one are now distinguishable.
|
|
185
254
|
*/
|
|
186
255
|
const _DERIVED_REASON: Readonly<Record<string, string>> = {
|
|
187
256
|
'Behaviour changes': 'rule/schema diffs, breaking commits or removed public surface',
|
|
188
257
|
'Default changes + migration': 'commits naming a default, migration or migrate',
|
|
189
258
|
'Security and correctness': 'security-scoped commits or fixes to executable surface',
|
|
190
259
|
'Honest nulls': 'commits recording a null, waived or falsified result',
|
|
260
|
+
'Known limitations': 'commits declaring a residual, known limit or uncovered case',
|
|
191
261
|
};
|
|
192
262
|
|
|
193
263
|
/**
|
|
@@ -204,7 +274,19 @@ const _DERIVED_REASON: Readonly<Record<string, string>> = {
|
|
|
204
274
|
* - Honest nulls: subject or body carrying one of the recorded-null forms —
|
|
205
275
|
* the literal marker, a waived-rather-than-met condition, a published or
|
|
206
276
|
* recorded null, an archival on a roadmap's own falsifier.
|
|
207
|
-
* - Known limitations:
|
|
277
|
+
* - Known limitations: subject or body carrying one of the self-declared
|
|
278
|
+
* residual forms, OR a touched EXECUTABLE file whose text carries one. The
|
|
279
|
+
* second half is what makes the label reachable at all: a residual is
|
|
280
|
+
* written where the code that has it lives, and `6b5c574` — the commit that
|
|
281
|
+
* moved detector E into `_lib/dropped_decision.ts` with its two named
|
|
282
|
+
* false-positive paths — says nothing about a limit in its own subject or
|
|
283
|
+
* body. It needs `opts.readTouchedFile`; without a reader the label falls
|
|
284
|
+
* back to the subject/body half alone, which is the pure-metadata behaviour
|
|
285
|
+
* every other label has.
|
|
286
|
+
*
|
|
287
|
+
* Scoped to executable surface on purpose (Risk 1 of the roadmap that added
|
|
288
|
+
* it): a residual declared in a rule or a roadmap is a plan, a residual
|
|
289
|
+
* declared in shipped code is a property of the release.
|
|
208
290
|
*
|
|
209
291
|
* Derivation is deliberately conservative: a false red makes every release
|
|
210
292
|
* annoying, a miss only returns the head to the pre-gate state. Conservative
|
|
@@ -220,11 +302,37 @@ const _DERIVED_REASON: Readonly<Record<string, string>> = {
|
|
|
220
302
|
*/
|
|
221
303
|
export function derive_category_hits(
|
|
222
304
|
commits: readonly SpanCommit[],
|
|
305
|
+
opts: DeriveOptions = {},
|
|
223
306
|
): Record<string, CategoryHit[]> {
|
|
224
307
|
const out: Record<string, CategoryHit[]> = {};
|
|
225
308
|
for (const label of HEAD_LABELS) {
|
|
226
309
|
out[label] = [];
|
|
227
310
|
}
|
|
311
|
+
// One verdict per path for the whole span, not per commit: a file touched
|
|
312
|
+
// by eleven commits is read once, and the eleven commits then agree by
|
|
313
|
+
// construction. Memoising the VERDICT rather than the text also keeps the
|
|
314
|
+
// peak memory of a wide span flat.
|
|
315
|
+
const residualPath = new Map<string, boolean>();
|
|
316
|
+
const _declares_residual_file = (files: SpanCommit['files']): string | null => {
|
|
317
|
+
if (!opts.readTouchedFile) {
|
|
318
|
+
return null;
|
|
319
|
+
}
|
|
320
|
+
for (const f of files) {
|
|
321
|
+
if (f.status.startsWith('D') || !_is_executable_path(f.path)) {
|
|
322
|
+
continue;
|
|
323
|
+
}
|
|
324
|
+
let verdict = residualPath.get(f.path);
|
|
325
|
+
if (verdict === undefined) {
|
|
326
|
+
const text = opts.readTouchedFile(f.path);
|
|
327
|
+
verdict = text !== null && _RESIDUAL_FORMS.some((re) => re.test(text));
|
|
328
|
+
residualPath.set(f.path, verdict);
|
|
329
|
+
}
|
|
330
|
+
if (verdict) {
|
|
331
|
+
return f.path;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
return null;
|
|
335
|
+
};
|
|
228
336
|
for (const c of commits) {
|
|
229
337
|
const scopeMatch = /^\w+\(([^)]*)\)!?:/u.exec(c.subject);
|
|
230
338
|
const scope = scopeMatch ? scopeMatch[1]! : '';
|
|
@@ -256,6 +364,17 @@ export function derive_category_hits(
|
|
|
256
364
|
if (_NULL_FORMS.some((re) => re.test(subjectAndBody))) {
|
|
257
365
|
out['Honest nulls']!.push({ sha: c.sha, text: c.subject });
|
|
258
366
|
}
|
|
367
|
+
if (_RESIDUAL_FORMS.some((re) => re.test(subjectAndBody))) {
|
|
368
|
+
out['Known limitations']!.push({ sha: c.sha, text: c.subject });
|
|
369
|
+
} else {
|
|
370
|
+
const declaring = _declares_residual_file(c.files);
|
|
371
|
+
if (declaring !== null) {
|
|
372
|
+
out['Known limitations']!.push({
|
|
373
|
+
sha: c.sha,
|
|
374
|
+
text: `${c.subject} (${declaring} declares a residual)`,
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
}
|
|
259
378
|
}
|
|
260
379
|
return out;
|
|
261
380
|
}
|
|
@@ -265,8 +384,11 @@ export function derive_category_hits(
|
|
|
265
384
|
* reports to a human. Derived from the structured hits so the two can never
|
|
266
385
|
* disagree.
|
|
267
386
|
*/
|
|
268
|
-
export function derive_categories(
|
|
269
|
-
|
|
387
|
+
export function derive_categories(
|
|
388
|
+
commits: readonly SpanCommit[],
|
|
389
|
+
opts: DeriveOptions = {},
|
|
390
|
+
): Record<string, string[]> {
|
|
391
|
+
const hits = derive_category_hits(commits, opts);
|
|
270
392
|
const out: Record<string, string[]> = {};
|
|
271
393
|
for (const label of HEAD_LABELS) {
|
|
272
394
|
out[label] = (hits[label] ?? []).map((h) => `${h.sha.slice(0, 7)} ${h.text}`);
|
|
@@ -571,6 +693,73 @@ export function collect_span_commits(from: string | null, to: string, cwd: strin
|
|
|
571
693
|
return parse_git_log(r.stdout);
|
|
572
694
|
}
|
|
573
695
|
|
|
696
|
+
/**
|
|
697
|
+
* Cap on distinct blobs one derivation will read.
|
|
698
|
+
*
|
|
699
|
+
* A bound and not a tuning knob: the `15.0.0..16.0.0` span touches 52 distinct
|
|
700
|
+
* executable paths, so the cap is an order of magnitude of headroom over the
|
|
701
|
+
* widest span measured. It exists so a pathological range (an era-spanning
|
|
702
|
+
* `--from`) cannot turn a gate into a thousand `git show` spawns. Hitting it
|
|
703
|
+
* degrades the label to the subject/body half rather than failing the gate,
|
|
704
|
+
* which is the same best-effort stance the rest of this derivation takes.
|
|
705
|
+
*/
|
|
706
|
+
export const RESIDUAL_BLOB_CAP = 600;
|
|
707
|
+
|
|
708
|
+
/**
|
|
709
|
+
* A `readTouchedFile` backed by `git show <ref>:<path>`, for the callers that
|
|
710
|
+
* have a repository.
|
|
711
|
+
*
|
|
712
|
+
* Reads at a REF rather than from the working tree on purpose: the gate runs
|
|
713
|
+
* on a release branch whose checkout is the release commit, and a derivation
|
|
714
|
+
* that read the worktree would answer about the checkout instead of about the
|
|
715
|
+
* span it was handed. `git show` failing (path absent at that ref, binary,
|
|
716
|
+
* submodule) returns null, which the derivation treats as unsubstantiated.
|
|
717
|
+
*/
|
|
718
|
+
export function make_span_file_reader(
|
|
719
|
+
ref: string,
|
|
720
|
+
cwd: string,
|
|
721
|
+
cap: number = RESIDUAL_BLOB_CAP,
|
|
722
|
+
): (path: string) => string | null {
|
|
723
|
+
let reads = 0;
|
|
724
|
+
return (p: string): string | null => {
|
|
725
|
+
if (reads >= cap) {
|
|
726
|
+
return null;
|
|
727
|
+
}
|
|
728
|
+
reads++;
|
|
729
|
+
const r = spawnSync('git', ['show', `${ref}:${p}`], {
|
|
730
|
+
encoding: 'utf-8',
|
|
731
|
+
cwd,
|
|
732
|
+
maxBuffer: 16 * 1024 * 1024,
|
|
733
|
+
});
|
|
734
|
+
return r.status === 0 ? r.stdout : null;
|
|
735
|
+
};
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
/**
|
|
739
|
+
* The whole span → curated-head prefill, in one call.
|
|
740
|
+
*
|
|
741
|
+
* The composition lives here rather than at the call site because the span's
|
|
742
|
+
* end ref and the file reader's ref MUST be the same one: `Known limitations`
|
|
743
|
+
* reads file CONTENT at a ref, so a caller that collected the span at `to`
|
|
744
|
+
* while reading blobs at some other ref would derive a head describing two
|
|
745
|
+
* different trees. Pairing them in one function makes that mismatch
|
|
746
|
+
* unexpressible rather than merely discouraged.
|
|
747
|
+
*
|
|
748
|
+
* Throws whatever `collect_span_commits` throws. Whether a git failure is
|
|
749
|
+
* fatal or degrades to the `_none_` skeleton is the caller's decision, and it
|
|
750
|
+
* stays the caller's — the generator catches, the gate does not.
|
|
751
|
+
*/
|
|
752
|
+
export function derive_head_prefill(
|
|
753
|
+
from: string | null,
|
|
754
|
+
to: string,
|
|
755
|
+
cwd: string,
|
|
756
|
+
): Record<string, string> {
|
|
757
|
+
const span = collect_span_commits(from, to, cwd);
|
|
758
|
+
return render_derived_head_values(
|
|
759
|
+
derive_category_hits(span, { readTouchedFile: make_span_file_reader(to, cwd) }),
|
|
760
|
+
);
|
|
761
|
+
}
|
|
762
|
+
|
|
574
763
|
/** Latest reachable release tag before `ref`, or null when there is none. */
|
|
575
764
|
export function previous_release_tag(ref: string, cwd: string): string | null {
|
|
576
765
|
const r = spawnSync(
|