session-orchestrator 5.3.0 → 5.5.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/.agents/skills/claude-md-drift-check/SKILL.md +1 -1
- package/.agents/skills/test-audit/SKILL.md +21 -0
- package/.agents/skills/test-audit/agents/openai.yaml +5 -0
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.codex-plugin/skills/claude-md-drift-check/SKILL.md +1 -1
- package/.codex-plugin/skills/test-audit/SKILL.md +21 -0
- package/.codex-plugin/skills/test-audit/agents/openai.yaml +5 -0
- package/.cursor/commands/test-audit.md +14 -0
- package/.cursor/rules/060-evolve.mdc +28 -13
- package/.cursor/skills/claude-md-drift-check/SKILL.md +1 -1
- package/.cursor/skills/test-audit/SKILL.md +12 -0
- package/.cursor-plugin/plugin.json +1 -1
- package/.orchestrator/policy/blocked-commands.json +1 -1
- package/AGENTS.md +9 -31
- package/CHANGELOG.md +162 -0
- package/README.md +14 -10
- package/docs/agent-authoring.md +2 -2
- package/docs/baseline.md +10 -1
- package/docs/ci-setup.md +154 -4
- package/docs/components.md +11 -11
- package/docs/events-schema.md +25 -19
- package/docs/install.md +14 -2
- package/docs/migration-v4.md +24 -17
- package/docs/persona-panel.md +5 -4
- package/docs/plugin-architecture-v3.md +1 -1
- package/docs/rule-authoring.md +27 -12
- package/docs/scope-collision-guard.md +40 -16
- package/docs/session-config-reference.md +61 -12
- package/docs/session-config-template.md +11 -2
- package/docs/vault-docs-architecture.md +8 -4
- package/hooks/_lib/hook-import-set.json +42 -29
- package/hooks/_lib/lock-bootstrap.mjs +118 -26
- package/hooks/config-protection.mjs +1 -1
- package/hooks/enforce-commands.mjs +28 -13
- package/hooks/enforce-scope.mjs +201 -23
- package/hooks/hooks-codex.json +1 -1
- package/hooks/hooks-cursor.json +5 -0
- package/hooks/hooks-pi.json +5 -0
- package/hooks/hooks.json +6 -1
- package/hooks/on-session-start.mjs +57 -2
- package/hooks/on-stop.mjs +70 -168
- package/hooks/post-bash-write-verify.mjs +98 -17
- package/hooks/post-edit-validate.mjs +15 -5
- package/hooks/post-tool-batch-wave-signal.mjs +32 -152
- package/hooks/pre-bash-memory-propose-audit.mjs +71 -10
- package/hooks/pre-bash-sessions-ledger-guard.mjs +28 -2
- package/hooks/pre-bash-staging-fence.mjs +29 -8
- package/hooks/pre-edit-sessions-ledger-guard.mjs +162 -0
- package/hooks/pre-task-scope-disjoint.mjs +1143 -279
- package/hooks/subagent-telemetry.mjs +96 -19
- package/hooks/wave-scope-commit-guard.mjs +168 -72
- package/package.json +2 -6
- package/pi/prompts/test-audit.md +12 -0
- package/rules/README.md +6 -1
- package/rules/_index.md +3 -3
- package/rules/always-on/bash-harness-pitfalls.md +7 -1
- package/rules/opt-in-domain/prompt-caching.md +5 -1
- package/rules/opt-in-stack/backend-data.md +9 -1
- package/rules/opt-in-stack/backend.md +7 -1
- package/rules/opt-in-stack/frontend.md +6 -1
- package/rules/opt-in-stack/security-web.md +7 -1
- package/rules/opt-in-stack/swift.md +5 -1
- package/scripts/apply-session-learnings.mjs +513 -0
- package/scripts/archive-closed-prds.mjs +40 -12
- package/scripts/autopilot.mjs +57 -54
- package/scripts/backfill-abandoned-sessions.mjs +81 -6
- package/scripts/backfill-learnings-from-vault.mjs +49 -22
- package/scripts/baseline-archetypes.mjs +1 -1
- package/scripts/check-package-manager.mjs +62 -5
- package/scripts/codex-install.mjs +3 -0
- package/scripts/cursor-install.mjs +47 -6
- package/scripts/emit-session.mjs +298 -2
- package/scripts/export-hw-learnings.mjs +40 -10
- package/scripts/fleet-checkin.mjs +170 -0
- package/scripts/lib/agent-frontmatter.mjs +3 -3
- package/scripts/lib/auto-dream.mjs +7 -6
- package/scripts/lib/autopilot/flags.mjs +6 -1
- package/scripts/lib/autopilot/loop.mjs +32 -13
- package/scripts/lib/autopilot/stall-sampler.mjs +13 -9
- package/scripts/lib/baseline-archetypes.mjs +41 -22
- package/scripts/lib/blocked-commands-policy.mjs +40 -0
- package/scripts/lib/common.mjs +41 -0
- package/scripts/lib/config/host-paths.mjs +79 -0
- package/scripts/lib/config/persona-gate-wave.mjs +3 -3
- package/scripts/lib/config/reaper.mjs +7 -6
- package/scripts/lib/config/vault-integration.mjs +151 -16
- package/scripts/lib/config-schema.mjs +13 -0
- package/scripts/lib/config.mjs +75 -10
- package/scripts/lib/eval/engine.mjs +13 -0
- package/scripts/lib/events-retention-banner.mjs +393 -0
- package/scripts/lib/events-rotation.mjs +21 -6
- package/scripts/lib/events.mjs +72 -5
- package/scripts/lib/fleet-protocol.mjs +288 -0
- package/scripts/lib/gates/gate-baseline.mjs +13 -3
- package/scripts/lib/gates/gate-full.mjs +7 -2
- package/scripts/lib/gates/gate-helpers.mjs +93 -2
- package/scripts/lib/gates/gate-incremental.mjs +23 -22
- package/scripts/lib/gates/gate-per-file.mjs +16 -7
- package/scripts/lib/hardening.mjs +1 -0
- package/scripts/lib/harness-audit/categories/category4.mjs +8 -6
- package/scripts/lib/instruction-budget-guard.mjs +77 -11
- package/scripts/lib/learnings/expiry-sweep.mjs +420 -22
- package/scripts/lib/learnings/io.mjs +274 -37
- package/scripts/lib/learnings/schema.mjs +163 -15
- package/scripts/lib/learnings/sizing-subject.mjs +2 -2
- package/scripts/lib/lock-reaper.mjs +38 -14
- package/scripts/lib/maintenance-due-banner.mjs +23 -8
- package/scripts/lib/memory-proposals/schema.mjs +11 -5
- package/scripts/lib/named-baseline-resolver.mjs +53 -28
- package/scripts/lib/named-vault-resolver.mjs +147 -5
- package/scripts/lib/orphan-reaper/defaults.mjs +41 -0
- package/scripts/lib/orphan-reaper/no-follow-append.mjs +87 -0
- package/scripts/lib/orphan-reaper/ps-snapshot.mjs +181 -0
- package/scripts/lib/orphan-reaper/reaper-audit.mjs +323 -0
- package/scripts/lib/orphan-reaper/reaper-decide.mjs +395 -0
- package/scripts/lib/orphan-reaper/scan-throttle.mjs +144 -0
- package/scripts/lib/orphan-reaper/scan.mjs +510 -0
- package/scripts/lib/orphan-reaper/trigger.mjs +173 -0
- package/scripts/lib/orphan-reaper.mjs +47 -1315
- package/scripts/lib/owner-yaml.mjs +104 -6
- package/scripts/lib/persona-panel/catalog-loader.mjs +1 -1
- package/scripts/lib/platform.mjs +206 -2
- package/scripts/lib/plugin-update-banner.mjs +3 -1
- package/scripts/lib/process-group.mjs +134 -22
- package/scripts/lib/project-hygiene.mjs +21 -1
- package/scripts/lib/quality-gate.mjs +45 -5
- package/scripts/lib/resource-probe.mjs +1 -1
- package/scripts/lib/rule-loader.mjs +100 -62
- package/scripts/lib/rules-sync.mjs +27 -12
- package/scripts/lib/scope-baseline.mjs +119 -29
- package/scripts/lib/scope-echo.mjs +7 -0
- package/scripts/lib/scope-gate.mjs +194 -27
- package/scripts/lib/session-close-backfill.mjs +129 -4
- package/scripts/lib/session-end/tail-runner.mjs +10 -5
- package/scripts/lib/session-lock-shape.mjs +6 -3
- package/scripts/lib/session-lock.mjs +320 -67
- package/scripts/lib/session-record-repair.mjs +183 -26
- package/scripts/lib/session-registry.mjs +67 -17
- package/scripts/lib/session-schema/constants.mjs +30 -4
- package/scripts/lib/session-schema/validator.mjs +28 -1
- package/scripts/lib/session-start-probes.mjs +242 -68
- package/scripts/lib/session-token-rollup.mjs +252 -54
- package/scripts/lib/sessions-canonical.mjs +100 -9
- package/scripts/lib/sessions-staleness-banner.mjs +3 -1
- package/scripts/lib/sh-quote.mjs +29 -0
- package/scripts/lib/subagents-schema.mjs +30 -3
- package/scripts/lib/tail-window.mjs +27 -3
- package/scripts/lib/telemetry/pricing.mjs +121 -71
- package/scripts/lib/telemetry/sync.mjs +17 -0
- package/scripts/lib/tests-src-ratio.mjs +215 -23
- package/scripts/lib/tmux-layout/layouts.mjs +1 -11
- package/scripts/lib/tmux-layout/telemetry-stats.mjs +12 -0
- package/scripts/lib/tmux-layout/tmux-shell.mjs +2 -11
- package/scripts/lib/ux-grill/reconcile.mjs +1 -1
- package/scripts/lib/validate/check-agents.mjs +1 -1
- package/scripts/lib/validate/check-hooks-symmetry.mjs +5 -0
- package/scripts/lib/validate/check-learnings-shell-writes.mjs +214 -0
- package/scripts/lib/validate/check-test-value-bans.mjs +388 -27
- package/scripts/lib/validate/check-unicode-safety.mjs +1 -0
- package/scripts/lib/validate/check-unwired-features.mjs +1 -1
- package/scripts/lib/validate/check-vcs-repo-flag.mjs +1 -1
- package/scripts/lib/validate-vendored-rules.mjs +206 -81
- package/scripts/lib/vault-mirror/auto-commit.mjs +5 -3
- package/scripts/lib/vault-mirror/namespace.mjs +47 -26
- package/scripts/lib/vault-mirror/process.mjs +350 -62
- package/scripts/lib/vault-mirror/pseudonym-map.mjs +14 -5
- package/scripts/lib/vault-mirror/render-learnings.mjs +66 -3
- package/scripts/lib/vault-mirror/render-sessions.mjs +28 -4
- package/scripts/lib/vault-mirror/telemetry.mjs +25 -11
- package/scripts/lib/vault-status/board-writer.mjs +53 -12
- package/scripts/lib/vault-status/narrative-mirror.mjs +40 -9
- package/scripts/lib/vcs-repo-spec.mjs +8 -0
- package/scripts/lib/wave-executor/dispatch-common.mjs +10 -18
- package/scripts/lib/wave-executor/foreign-dispatch.mjs +1 -1
- package/scripts/lib/wave-executor/remote-dispatch.mjs +1 -1
- package/scripts/lib/wave-resource-gate.mjs +34 -8
- package/scripts/materialize-wave-scope.mjs +7 -4
- package/scripts/memory-propose.mjs +18 -5
- package/scripts/release-session-lock.mjs +2 -1
- package/scripts/release.mjs +11 -3
- package/scripts/repair-invalid-sessions.mjs +37 -4
- package/scripts/run-migrate-v2-cross-repo.mjs +171 -31
- package/scripts/run-quality-gate.mjs +331 -307
- package/scripts/self-update.mjs +229 -0
- package/scripts/site-numbers.mjs +163 -5
- package/scripts/sweep-expired-learnings.mjs +603 -20
- package/scripts/sweep-expired-rules.mjs +2 -1
- package/scripts/validate-plugin.mjs +7 -0
- package/scripts/validate-wave-scope.mjs +21 -2
- package/scripts/vault-backfill.mjs +50 -37
- package/scripts/vault-integration-watcher.mjs +2 -1
- package/scripts/vault-mirror.mjs +238 -75
- package/scripts/wave-scope-binding.mjs +2 -1
- package/skills/_shared/config-reading.md +3 -3
- package/skills/_shared/fleet-protocol.md +134 -0
- package/skills/_shared/state-ownership.md +41 -12
- package/skills/autopilot/SKILL.md +25 -11
- package/skills/bootstrap/SKILL.md +6 -4
- package/skills/bootstrap/_shared-template.md +97 -2
- package/skills/bootstrap/fast-template.md +4 -1
- package/skills/bootstrap/private-contract.md +2 -1
- package/skills/bootstrap/public-fallback.md +6 -3
- package/skills/bootstrap/references/bootstrap-refresh-lock-flow.md +5 -3
- package/skills/bootstrap/references/bootstrap-retroactive-flow.md +2 -1
- package/skills/bootstrap/standard-template.md +2 -0
- package/skills/claude-md-drift-check/SKILL.md +10 -10
- package/skills/claude-md-drift-check/checker.mjs +26 -18
- package/skills/discovery/probes/ssot-code-diff.mjs +12 -6
- package/skills/discovery/probes/vault-narrative-staleness.mjs +6 -2
- package/skills/discovery/probes/vault-staleness.mjs +9 -3
- package/skills/docs-orchestrator/SKILL.md +12 -5
- package/skills/docs-orchestrator/audience-mapping.md +5 -3
- package/skills/evolve/SKILL.md +13 -4
- package/skills/evolve/references/evolve-analyze-mode.md +42 -18
- package/skills/memory-cleanup/SKILL.md +1 -1
- package/skills/persona-panel/SKILL.md +2 -2
- package/skills/persona-panel/persona-format.md +2 -2
- package/skills/persona-panel/presets/designer-lens.md +1 -1
- package/skills/persona-panel/presets/engineer-lens.md +1 -1
- package/skills/persona-panel/presets/pm-lens.md +1 -1
- package/skills/plan/mode-retro.md +19 -4
- package/skills/quality-gates/SKILL.md +6 -4
- package/skills/remote-offload/SKILL.md +4 -2
- package/skills/session-end/learning-patterns.md +23 -13
- package/skills/session-end/metrics-collection.md +6 -7
- package/skills/session-end/phase-3-2-docs-verification.md +7 -6
- package/skills/session-end/plan-verification.md +25 -9
- package/skills/session-end/references/phase-3-documentation-updates.md +13 -3
- package/skills/session-end/references/phase-4a-worktree-cleanup.md +2 -0
- package/skills/session-end/references/session-summary-template.md +1 -1
- package/skills/session-end/session-metrics-write.md +65 -68
- package/skills/session-plan/SKILL.md +0 -3
- package/skills/session-start/SKILL.md +8 -2
- package/skills/session-start/references/operations-contract.md +6 -0
- package/skills/session-start/references/phase-1-2-session-lock.md +32 -7
- package/skills/session-start/references/phase-1-7-vault-status-board.md +1 -1
- package/skills/session-start/references/phase-4-ssot-environment-check.md +10 -3
- package/skills/test-audit/SKILL.md +152 -0
- package/skills/test-audit/references/campaign.md +111 -0
- package/skills/test-audit/references/mutate.sh +50 -0
- package/skills/vault-mirror/SKILL.md +21 -11
- package/skills/wave-executor/SKILL.md +2 -2
- package/skills/wave-executor/circuit-breaker.md +1 -1
- package/skills/wave-executor/references/wave-executor-state-init.md +3 -0
- package/skills/wave-executor/references/wave-loop-dispatch.md +11 -1
- package/skills/wave-executor/references/wave-loop-review.md +4 -6
- package/skills/wave-executor/references/wave-loop-scope-manifest.md +13 -5
- package/templates/personas/README.md +5 -5
- package/templates/personas/accounting-compliance.v1.md +1 -1
- package/templates/personas/accounting-tax-advisor.v1.md +1 -1
- package/templates/personas/buyer-p1-cto.v1.md +1 -1
- package/templates/personas/buyer-p2-kanzlei.v1.md +1 -1
- package/templates/personas/buyer-p3-build.v1.md +1 -1
- package/templates/personas/buyer-p4-tech-veto.v1.md +1 -1
- package/templates/personas/buyer-p5-solo.v1.md +1 -1
- package/templates/personas/buyer-p6-ld.v1.md +1 -1
- package/templates/personas/klima-ai-expert.v1.md +1 -1
- package/templates/personas/klima-physicist.v1.md +1 -1
|
@@ -47,6 +47,16 @@
|
|
|
47
47
|
* tier-gate conditionals `applyGates` already implements (the `context`
|
|
48
48
|
* param below is the exact mechanism rule-loader exposes for this).
|
|
49
49
|
*
|
|
50
|
+
* #1449: that membership now matches what Claude Code actually loads. The
|
|
51
|
+
* loader used to skip a leading provenance comment before `---`, so a rule
|
|
52
|
+
* Claude Code loads always-on (it reads frontmatter only from line 1) counted
|
|
53
|
+
* here as path-scoped, and every consumer's always-on total was short by the
|
|
54
|
+
* vendored rules carrying that header. Such a file now counts as always-on —
|
|
55
|
+
* its displaced frontmatter as body bytes, since that is how Claude Code
|
|
56
|
+
* delivers it — and is listed in `defects` and on its own banner line. The
|
|
57
|
+
* list is report-only: it is not an `overBudget` term, so a defect never turns
|
|
58
|
+
* a budget verdict red.
|
|
59
|
+
*
|
|
50
60
|
* Cross-references:
|
|
51
61
|
* - "2026-06-20 instruction-budget audit" (#668 / #687; archived in the private Meta-Vault)
|
|
52
62
|
* - scripts/lib/rule-loader.mjs (always-on classification + tier-gate SSOT)
|
|
@@ -79,7 +89,11 @@
|
|
|
79
89
|
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
80
90
|
import { basename, join } from 'node:path';
|
|
81
91
|
import { scanEventsBackwards } from './events.mjs';
|
|
82
|
-
import {
|
|
92
|
+
import {
|
|
93
|
+
FRONTMATTER_NOT_AT_TOP,
|
|
94
|
+
loadApplicableRules,
|
|
95
|
+
parseGlobsFrontmatter,
|
|
96
|
+
} from './rule-loader.mjs';
|
|
83
97
|
|
|
84
98
|
/** Default directive ceiling (operator-chosen growth ratchet just above the ~457 baseline). */
|
|
85
99
|
export const DEFAULT_CEILING = 480;
|
|
@@ -1055,12 +1069,18 @@ function measureRuleCorpora(rulesDir) {
|
|
|
1055
1069
|
* bySurface: { coordinator: number, wave: number, always: number,
|
|
1056
1070
|
* generated: {bytes: number, files: number},
|
|
1057
1071
|
* pathScoped: {bytes: number, files: number} },
|
|
1072
|
+
* defects: string[],
|
|
1058
1073
|
* }}
|
|
1059
|
-
* perFile is sorted DESC by count.
|
|
1074
|
+
* perFile is sorted DESC by count. `defects` (#1449) lists, sorted by name,
|
|
1075
|
+
* the rule files whose frontmatter does not start on line 1 — Claude Code
|
|
1076
|
+
* ignores it, so they load always-on and are counted as such. It is
|
|
1077
|
+
* independent of `context` (such a file has no tier to gate on) and never
|
|
1078
|
+
* feeds `overBudget`. On missing/unreadable dir →
|
|
1060
1079
|
* { totalDirectives: 0, totalBytes: 0, perFile: [], ceiling, byteCeiling,
|
|
1061
1080
|
* overDirectiveBudget: false, overByteBudget: false, overBudget: false,
|
|
1062
1081
|
* severity: 'ok', bySurface: { coordinator: 0, wave: 0, always: 0,
|
|
1063
|
-
* generated: {bytes:0,files:0}, pathScoped: {bytes:0,files:0} }
|
|
1082
|
+
* generated: {bytes:0,files:0}, pathScoped: {bytes:0,files:0} },
|
|
1083
|
+
* defects: [] }.
|
|
1064
1084
|
*
|
|
1065
1085
|
* #931a verdict rule — `overBudget` is the OR of the two axes
|
|
1066
1086
|
* (`overDirectiveBudget || overByteBudget`), NOT a per-axis severity split:
|
|
@@ -1165,6 +1185,7 @@ export function computeInstructionBudget(opts = {}) {
|
|
|
1165
1185
|
generated: { bytes: 0, files: 0 },
|
|
1166
1186
|
pathScoped: { bytes: 0, files: 0 },
|
|
1167
1187
|
},
|
|
1188
|
+
defects: [],
|
|
1168
1189
|
};
|
|
1169
1190
|
|
|
1170
1191
|
let allEntries;
|
|
@@ -1256,6 +1277,13 @@ export function computeInstructionBudget(opts = {}) {
|
|
|
1256
1277
|
const overPathScopedBudget = bySurface.pathScoped.bytes > pathScopedByteCeiling;
|
|
1257
1278
|
const overBudget = overDirectiveBudget || overByteBudget || overGeneratedBudget || overPathScopedBudget;
|
|
1258
1279
|
|
|
1280
|
+
// #1449: read off the untiered list — a defective file carries no meta, so
|
|
1281
|
+
// no tier gate drops it and `alwaysOnAll` holds every one of them.
|
|
1282
|
+
const defects = alwaysOnAll
|
|
1283
|
+
.filter((e) => e.defect === FRONTMATTER_NOT_AT_TOP)
|
|
1284
|
+
.map((e) => basename(e.path))
|
|
1285
|
+
.sort((a, b) => a.localeCompare(b));
|
|
1286
|
+
|
|
1259
1287
|
return {
|
|
1260
1288
|
totalDirectives,
|
|
1261
1289
|
totalBytes,
|
|
@@ -1271,12 +1299,21 @@ export function computeInstructionBudget(opts = {}) {
|
|
|
1271
1299
|
overBudget,
|
|
1272
1300
|
severity: overBudget ? 'warn' : 'ok',
|
|
1273
1301
|
bySurface,
|
|
1302
|
+
defects,
|
|
1274
1303
|
};
|
|
1275
1304
|
}
|
|
1276
1305
|
|
|
1277
1306
|
/** Ledger event the backlog number below is read from (`reconcile/engine.mjs`). */
|
|
1278
1307
|
const RECONCILE_EVENT = 'orchestrator.reconcile.completed';
|
|
1279
1308
|
|
|
1309
|
+
/**
|
|
1310
|
+
* Events-ledger window for the #1401 census (`events-retention-banner.mjs`):
|
|
1311
|
+
* `null` — {@link readLastReconcileCapped} wants the NEWEST reconcile record,
|
|
1312
|
+
* whose age no constant bounds; a pruned one reads as not measured (`null`,
|
|
1313
|
+
* rendered as absence), never as a measured `0`.
|
|
1314
|
+
*/
|
|
1315
|
+
export const REQUIRED_EVENTS_WINDOW_DAYS = null;
|
|
1316
|
+
|
|
1280
1317
|
/**
|
|
1281
1318
|
* Wall-clock budget for the backwards ledger walk. Deliberately small: this
|
|
1282
1319
|
* runs inside a session-start probe whose own budget is 2 s, and the number it
|
|
@@ -1351,6 +1388,21 @@ function formatNearPathScopedLine(budget, repoRoot) {
|
|
|
1351
1388
|
);
|
|
1352
1389
|
}
|
|
1353
1390
|
|
|
1391
|
+
/**
|
|
1392
|
+
* The #1449 defect line: rule files whose frontmatter Claude Code never reads.
|
|
1393
|
+
* Names every file — the fix is per file (move the text above `---` below the
|
|
1394
|
+
* closing fence), so a count alone would send the operator hunting.
|
|
1395
|
+
*
|
|
1396
|
+
* @param {string[]} defects - basenames from `computeInstructionBudget().defects`
|
|
1397
|
+
* @returns {string}
|
|
1398
|
+
*/
|
|
1399
|
+
function formatFrontmatterDefectLine(defects) {
|
|
1400
|
+
return (
|
|
1401
|
+
`⚠ ${defects.length} rule(s) carry frontmatter that Claude Code ignores ` +
|
|
1402
|
+
`(text before the opening ---): ${defects.join(', ')} — they load always-on.`
|
|
1403
|
+
);
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1354
1406
|
/**
|
|
1355
1407
|
* Banner wrapper — session-start Phase 4 convention.
|
|
1356
1408
|
*
|
|
@@ -1367,7 +1419,9 @@ function formatNearPathScopedLine(budget, repoRoot) {
|
|
|
1367
1419
|
*
|
|
1368
1420
|
* The message names WHICH axis breached (#931a) — a banner that only said
|
|
1369
1421
|
* "over budget" would leave the operator guessing whether to prune bullets or
|
|
1370
|
-
* prose. It stays
|
|
1422
|
+
* prose. It stays short because it renders at every session start: the breach
|
|
1423
|
+
* block is three lines, plus one line per extra finding (near-threshold,
|
|
1424
|
+
* frontmatter defect).
|
|
1371
1425
|
*
|
|
1372
1426
|
* @param {object} [opts] forwarded to computeInstructionBudget.
|
|
1373
1427
|
* @param {string} [opts.repoRoot] project root for the config read.
|
|
@@ -1382,8 +1436,10 @@ function formatNearPathScopedLine(budget, repoRoot) {
|
|
|
1382
1436
|
* raises it at {@link PATH_SCOPED_NEAR_THRESHOLD} of its ceiling, before the
|
|
1383
1437
|
* breach: that band used to be silent, and the ceiling then surfaced only
|
|
1384
1438
|
* inside `writeApprovedRules` — after the operator had approved rules it
|
|
1385
|
-
* refused to write.
|
|
1386
|
-
*
|
|
1439
|
+
* refused to write. Since #1449 a rule whose frontmatter is not on line 1
|
|
1440
|
+
* raises it too (one line naming the files), whether or not any axis is
|
|
1441
|
+
* close. The RETURN SHAPE is unchanged (`{severity:'warn', message}` |
|
|
1442
|
+
* null), so `session-start-probes.mjs` needs no new vocabulary.
|
|
1387
1443
|
*/
|
|
1388
1444
|
export function checkInstructionBudget(opts = {}) {
|
|
1389
1445
|
let cfg;
|
|
@@ -1455,18 +1511,27 @@ export function checkInstructionBudget(opts = {}) {
|
|
|
1455
1511
|
budget.pathScopedByteCeiling > 0 &&
|
|
1456
1512
|
budget.bySurface.pathScoped.bytes >= budget.pathScopedByteCeiling * PATH_SCOPED_NEAR_THRESHOLD;
|
|
1457
1513
|
|
|
1458
|
-
|
|
1514
|
+
// #1449 — reported on its own line, never folded into `overBudget`.
|
|
1515
|
+
const defectLine =
|
|
1516
|
+
budget.defects.length > 0 ? formatFrontmatterDefectLine(budget.defects) : null;
|
|
1517
|
+
|
|
1518
|
+
if (!budget.overBudget && !nearPathScoped && !defectLine) return null;
|
|
1459
1519
|
|
|
1460
1520
|
const nearLine = nearPathScoped ? formatNearPathScopedLine(budget, opts.repoRoot) : null;
|
|
1461
1521
|
|
|
1462
|
-
//
|
|
1463
|
-
// same remedy as the breach clause below (consolidate — never raise).
|
|
1522
|
+
// Nothing breached: one block per finding — the near-threshold line carries
|
|
1523
|
+
// the same remedy as the breach clause below (consolidate — never raise).
|
|
1464
1524
|
if (!budget.overBudget) {
|
|
1465
1525
|
return {
|
|
1466
1526
|
severity: 'warn',
|
|
1467
1527
|
message: [
|
|
1468
|
-
|
|
1469
|
-
|
|
1528
|
+
...(nearLine
|
|
1529
|
+
? [
|
|
1530
|
+
`⚠ ${nearLine}.`,
|
|
1531
|
+
' Consolidate generated rules per docs/rule-authoring.md § Consolidated rules; never raise the ceiling.',
|
|
1532
|
+
]
|
|
1533
|
+
: []),
|
|
1534
|
+
...(defectLine ? [defectLine] : []),
|
|
1470
1535
|
].join('\n'),
|
|
1471
1536
|
};
|
|
1472
1537
|
}
|
|
@@ -1523,6 +1588,7 @@ export function checkInstructionBudget(opts = {}) {
|
|
|
1523
1588
|
...(nearLine ? [` ${nearLine}.`] : []),
|
|
1524
1589
|
` Top files: ${top}`,
|
|
1525
1590
|
' See the instruction-budget audit (#687; archived in the private Meta-Vault) for the prune/demote list.',
|
|
1591
|
+
...(defectLine ? [defectLine] : []),
|
|
1526
1592
|
].join('\n');
|
|
1527
1593
|
|
|
1528
1594
|
return { severity: 'warn', message };
|