@event4u/agent-config 14.14.0 → 14.14.1
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 +33 -0
- package/README.md +1 -1
- package/dist/agent-src/commands/pr/create.md +16 -1
- package/dist/agent-src/contexts/execution/terminal-states.md +25 -4
- package/dist/agent-src/rules/missing-skill-recovery.md +2 -2
- package/dist/agent-src/rules/token-budget-discipline.md +2 -2
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/cli/registry.js +1 -0
- package/dist/cli-delegate/{chunk-ILMUPLGW.js → chunk-7RXIKF62.js} +159 -86
- package/dist/cli-delegate/cmd_conformance.js +1 -1
- package/dist/cli-delegate/cmd_doctor.js +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +5 -5
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +1 -1
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +2 -2
- package/dist/discovery/trust-report.md +1 -1
- package/dist/discovery/workspaces.json +2 -2
- package/dist/hooks/dispatch.js +528 -371
- package/dist/mcp/registry-manifest.json +2 -2
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +185 -98
- package/package.json +1 -1
- package/src/config/assurance-capability-registry.json +1 -1
- package/src/config/evaluator-budgets.json +4 -4
- package/src/config/gate-coverage.yml +62 -2
- package/src/config/gate-reachability-exemptions.json +1 -0
- package/src/config/gate-violation-baselines.json +4 -3
- package/src/config/web-launch-readiness.json +4 -2
- package/src/scripts/_cli/_doctor_emit.ts +71 -0
- package/src/scripts/_cli/_doctor_strict.ts +163 -0
- package/src/scripts/_cli/cmd_doctor.ts +16 -37
- package/src/scripts/_dispatch.bash +11 -0
- package/src/scripts/_lib/branch_convergence.ts +186 -0
- package/src/scripts/_lib/context_observation.ts +132 -0
- package/src/scripts/_lib/continuation_ladder.ts +188 -0
- package/src/scripts/_lib/experiment_binding.ts +95 -0
- package/src/scripts/_lib/ignored_blocker.ts +8 -1
- package/src/scripts/_lib/outcome_envelope.ts +6 -1
- package/src/scripts/_lib/outcome_vocabularies.ts +135 -5
- package/src/scripts/_lib/release_highlights.ts +12 -3
- package/src/scripts/_lib/repeated_failure.ts +19 -2
- package/src/scripts/_lib/runtime_journal.ts +11 -4
- package/src/scripts/check_agent_artifact_location.ts +337 -0
- package/src/scripts/check_artefact_count_messaging.ts +74 -8
- package/src/scripts/check_enforcement_coverage.ts +40 -1
- package/src/scripts/check_release_highlights.ts +17 -1
- package/src/scripts/check_web_launch_readiness.ts +310 -20
- package/src/scripts/evolution_lab.ts +53 -1
- package/src/scripts/generate_capability_matrix.ts +16 -9
- package/src/scripts/grade_target_readiness.ts +221 -2
- package/src/scripts/hook_effect_doctor.ts +47 -4
- package/src/scripts/hooks/run_continuation_hook.ts +78 -88
- package/src/scripts/hooks/session_eol_hook.ts +12 -1
- package/src/scripts/install-hooks.sh +18 -0
- package/src/scripts/lint_code_comments.ts +106 -1
- package/src/scripts/release_drill.ts +57 -1
- package/src/scripts/release_publication.ts +58 -0
- package/src/scripts/roadmap_context.ts +15 -0
- package/src/scripts/skill_scout.ts +633 -0
- package/src/scripts/sync_pr_branch.ts +521 -42
|
@@ -20,10 +20,14 @@
|
|
|
20
20
|
* - `check_command_count_messaging.ts` keeps the command-specific
|
|
21
21
|
* active-vs-shim split checks.
|
|
22
22
|
*
|
|
23
|
-
* Scope: flagship surfaces
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
23
|
+
* Scope: flagship surfaces (SURFACES below) PLUS every governed rule under
|
|
24
|
+
* `src/rules/` (RULE_SURFACE_DIR). Rules were the largest hole this gate had:
|
|
25
|
+
* they are the most-delivered surface this package ships — a wrong self-count
|
|
26
|
+
* there reaches every consumer session — and the list below named sixteen doc
|
|
27
|
+
* paths and no rule path. Dated census / analysis snapshots (SKILL_CENSUS,
|
|
28
|
+
* skills-taxonomy, positioning-evidence, …) carry point-in-time counts by
|
|
29
|
+
* design and are deliberately out of scope — the gate's charter is the surfaces
|
|
30
|
+
* a fresh reader treats as current.
|
|
27
31
|
*
|
|
28
32
|
* Exit codes: 0 clean · 1 drift or internal inconsistency.
|
|
29
33
|
*/
|
|
@@ -66,6 +70,41 @@ export const SURFACES: readonly string[] = [
|
|
|
66
70
|
// absent there. A gate must judge repo content, not untracked local state.
|
|
67
71
|
];
|
|
68
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Governed rules, enumerated rather than listed.
|
|
75
|
+
*
|
|
76
|
+
* A hand-maintained list of 120 rule paths would go stale on the first rule
|
|
77
|
+
* added, which is the drift class this gate exists to catch — so the rule
|
|
78
|
+
* surface is a directory, walked at run time.
|
|
79
|
+
*/
|
|
80
|
+
export const RULE_SURFACE_DIR = 'src/rules';
|
|
81
|
+
|
|
82
|
+
export function rule_surfaces(root: string = ROOT): string[] {
|
|
83
|
+
const dir = path.join(root, RULE_SURFACE_DIR);
|
|
84
|
+
if (!fs.existsSync(dir)) {
|
|
85
|
+
return [];
|
|
86
|
+
}
|
|
87
|
+
return fs
|
|
88
|
+
.readdirSync(dir)
|
|
89
|
+
.filter((f) => f.endsWith('.md'))
|
|
90
|
+
.sort()
|
|
91
|
+
.map((f) => `${RULE_SURFACE_DIR}/${f}`);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* A count that belongs to a dated measurement, not to this package's live
|
|
96
|
+
* totals.
|
|
97
|
+
*
|
|
98
|
+
* The gate's charter already excludes point-in-time snapshots; until now it
|
|
99
|
+
* could only express that by leaving a whole FILE out. A rule may carry a dated
|
|
100
|
+
* host measurement inside a paragraph of live prose, and neither excluding the
|
|
101
|
+
* rule nor rewriting the measurement to today's total is correct — the second
|
|
102
|
+
* falsifies recorded evidence. The marker is per line, and it is a claim a
|
|
103
|
+
* reviewer can falsify: the line must name the date or the artefact the figure
|
|
104
|
+
* was measured against.
|
|
105
|
+
*/
|
|
106
|
+
export const DATED_MEASUREMENT_MARKER = '<!-- count: dated -->';
|
|
107
|
+
|
|
69
108
|
/** kind → canonical-count resolver. "governed rules" is the canonical total
|
|
70
109
|
* phrasing for rules; bare "N rules" is NOT matched (too many legitimate
|
|
71
110
|
* subset scopes: kernel rules, router rules, maintainer-only rules …). */
|
|
@@ -108,6 +147,9 @@ export function scan_text(
|
|
|
108
147
|
for (const [kind, pattern] of KIND_PATTERNS) {
|
|
109
148
|
for (let i = 0; i < lines.length; i++) {
|
|
110
149
|
const re = new RegExp(pattern.source, pattern.flags);
|
|
150
|
+
if (lines[i]!.includes(DATED_MEASUREMENT_MARKER)) {
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
111
153
|
for (const m of lines[i]!.matchAll(re)) {
|
|
112
154
|
const found = Number.parseInt(m[2]!, 10);
|
|
113
155
|
(seen[kind] ??= new Set()).add(found);
|
|
@@ -219,6 +261,15 @@ export interface CoverageGap {
|
|
|
219
261
|
*
|
|
220
262
|
* A position counts as anchored when some `TARGETS` pattern for the same
|
|
221
263
|
* file, bound to a compatible kind, matches the same line.
|
|
264
|
+
*
|
|
265
|
+
* `src/rules/**` is scanned for VALUE drift but is deliberately excluded from
|
|
266
|
+
* this pass, and the reason is mechanical rather than stylistic: satisfying it
|
|
267
|
+
* would require `update_counts` to become a writer into `src/rules/`, where the
|
|
268
|
+
* kernel rules live behind `block_kernel_rule_writes`. A generator that must
|
|
269
|
+
* never touch part of its own target directory is a generator waiting to be
|
|
270
|
+
* disarmed by a path move. So a stale count in a rule fails on value and a human
|
|
271
|
+
* fixes it — the coverage claim this pass makes stays true of the surfaces it
|
|
272
|
+
* actually covers, instead of being widened into a claim it cannot keep.
|
|
222
273
|
*/
|
|
223
274
|
export function anchor_coverage_gaps(root: string = ROOT): CoverageGap[] {
|
|
224
275
|
const anchorsByFile = new Map<string, ReadonlyArray<[string, string]>>();
|
|
@@ -254,6 +305,16 @@ export function anchor_coverage_gaps(root: string = ROOT): CoverageGap[] {
|
|
|
254
305
|
|
|
255
306
|
export function main(argv: readonly string[] = process.argv.slice(2)): number {
|
|
256
307
|
const QUIET = argv.includes('--quiet');
|
|
308
|
+
// Enumerated, not listed. An empty walk means the rule tree moved and this
|
|
309
|
+
// gate is watching nothing — a dead scope, never a clean run.
|
|
310
|
+
const rules = rule_surfaces();
|
|
311
|
+
if (rules.length === 0) {
|
|
312
|
+
process.stderr.write(
|
|
313
|
+
`❌ check_artefact_count_messaging: ${RULE_SURFACE_DIR}/ resolved to no .md file — ` +
|
|
314
|
+
'the rule surface moved and this gate would pass by blindness.\n',
|
|
315
|
+
);
|
|
316
|
+
return 1;
|
|
317
|
+
}
|
|
257
318
|
// This gate walks no tree — it guards a hand-maintained surface list, and
|
|
258
319
|
// every missing entry is skipped with a warning so nothing hard-breaks on a
|
|
259
320
|
// doc rename. That tolerance is also the failure mode: a repo-wide docs
|
|
@@ -262,7 +323,7 @@ export function main(argv: readonly string[] = process.argv.slice(2)): number {
|
|
|
262
323
|
try {
|
|
263
324
|
assertWatchlistResolves({
|
|
264
325
|
gate: 'check_artefact_count_messaging',
|
|
265
|
-
candidates: [...SURFACES, ...STRUCTURED_SURFACES.map((s) => s.file)],
|
|
326
|
+
candidates: [...SURFACES, ...STRUCTURED_SURFACES.map((s) => s.file), ...rules],
|
|
266
327
|
repoRoot: ROOT,
|
|
267
328
|
});
|
|
268
329
|
} catch (exc) {
|
|
@@ -285,7 +346,7 @@ export function main(argv: readonly string[] = process.argv.slice(2)): number {
|
|
|
285
346
|
|
|
286
347
|
const allFindings: Finding[] = [];
|
|
287
348
|
const global_seen: Record<string, Set<number>> = {};
|
|
288
|
-
for (const rel of SURFACES) {
|
|
349
|
+
for (const rel of [...SURFACES, ...rules]) {
|
|
289
350
|
const p = path.join(ROOT, rel);
|
|
290
351
|
if (!fs.existsSync(p)) {
|
|
291
352
|
process.stderr.write(` ⚠️ surface missing (skipped): ${rel}\n`);
|
|
@@ -347,8 +408,13 @@ export function main(argv: readonly string[] = process.argv.slice(2)): number {
|
|
|
347
408
|
process.stdout.write(` internal inconsistency — ${line}\n`);
|
|
348
409
|
}
|
|
349
410
|
process.stdout.write(
|
|
350
|
-
'\nFix: run `./scripts-run src/scripts/update_counts`
|
|
351
|
-
'
|
|
411
|
+
'\nFix: on a flagship surface, run `./scripts-run src/scripts/update_counts` —\n' +
|
|
412
|
+
'every anchored position is generator-written, so never hand-type one there.\n' +
|
|
413
|
+
`Under ${RULE_SURFACE_DIR}/ the generator does not write (the kernel rules live\n` +
|
|
414
|
+
'there behind block_kernel_rule_writes), so a rule count is a hand edit: correct\n' +
|
|
415
|
+
'the number, or — if the figure is a dated measurement rather than a live\n' +
|
|
416
|
+
`self-count — mark that line \`${DATED_MEASUREMENT_MARKER}\` and say what it was\n` +
|
|
417
|
+
'measured against.\n',
|
|
352
418
|
);
|
|
353
419
|
}
|
|
354
420
|
|
|
@@ -628,6 +628,26 @@ export interface Summary {
|
|
|
628
628
|
frequency_gap: number;
|
|
629
629
|
/** Rules with no `obligation_frequency` to join — the nine kernel rules. */
|
|
630
630
|
frequency_unclassified: number;
|
|
631
|
+
/**
|
|
632
|
+
* The three classes that make `undeclared` readable.
|
|
633
|
+
*
|
|
634
|
+
* WHY THEY SHIP IN THE ARTEFACT. `undeclared` is the number reviewers quote,
|
|
635
|
+
* and quoted bare it reads as a backlog of rules somebody forgot to wire.
|
|
636
|
+
* Most of it is nothing of the kind. `kernel_denied` rules cannot carry an
|
|
637
|
+
* `enforced_by` field at all — `block_kernel_rule_writes` refuses the write
|
|
638
|
+
* with no agent-accessible override, so their absence is structural.
|
|
639
|
+
* `observer` rules have a carrier that fires and cannot block by design.
|
|
640
|
+
* `carrier_less` rules have no machine carrier of any kind.
|
|
641
|
+
*
|
|
642
|
+
* A reader subtracting these from `undeclared` gets the population where
|
|
643
|
+
* wiring is actually the missing thing — and, more usefully, sees at a glance
|
|
644
|
+
* that the observer set (10) is the reachable one: a floor set against the
|
|
645
|
+
* full `undeclared` would stall in its second release and be ignored, which
|
|
646
|
+
* is the failure `check_release_highlights.ts` already documents for its own
|
|
647
|
+
* warning.
|
|
648
|
+
*/
|
|
649
|
+
kernel_denied: number;
|
|
650
|
+
carrier_less: number;
|
|
631
651
|
/**
|
|
632
652
|
* The denominator every figure above is taken over, WITH its frame. See
|
|
633
653
|
* {@link denominator_frames} for why the frame ships even when the two
|
|
@@ -652,6 +672,14 @@ export function summarise(rows: RuleCoverage[]): Summary {
|
|
|
652
672
|
blocking_pct: rows.length === 0 ? 0 : Math.round((blocking / rows.length) * 1000) / 10,
|
|
653
673
|
frequency_gap: count((r) => r.frequency_verdict === 'gap'),
|
|
654
674
|
frequency_unclassified: count((r) => r.frequency_verdict === 'unclassified'),
|
|
675
|
+
kernel_denied: count(
|
|
676
|
+
(r) => KERNEL_RULE_ID_SET.has(r.id) && r.frequency_verdict === 'unclassified',
|
|
677
|
+
),
|
|
678
|
+
carrier_less: count(
|
|
679
|
+
(r) =>
|
|
680
|
+
r.declared.length > 0 &&
|
|
681
|
+
r.declared.every((d) => d.startsWith('observer:maintainer-review')),
|
|
682
|
+
),
|
|
655
683
|
frames: denominator_frames(rows.length),
|
|
656
684
|
};
|
|
657
685
|
}
|
|
@@ -779,7 +807,13 @@ function main(argv: string[]): number {
|
|
|
779
807
|
'blocking and in that bucket at once. Coverage is a ratchet: --check fails ' +
|
|
780
808
|
'when blocking falls, or unwired / local_only / missing / frequency_gap ' +
|
|
781
809
|
'rises. Regenerate intentionally with --write-baseline when the change is ' +
|
|
782
|
-
'the point.'
|
|
810
|
+
'the point. READ `undeclared` WITH ITS THREE CLASSES, never bare: ' +
|
|
811
|
+
'`kernel_denied` cannot carry an enforced_by field at all ' +
|
|
812
|
+
'(block_kernel_rule_writes refuses the write, no agent-accessible ' +
|
|
813
|
+
'override), `observer` has a carrier that fires and cannot block by ' +
|
|
814
|
+
'design, and `carrier_less` has no machine carrier of any kind. The ' +
|
|
815
|
+
'reachable population is the observer set, not `undeclared` — a floor ' +
|
|
816
|
+
'set against the full number would stall in its second release.',
|
|
783
817
|
summary,
|
|
784
818
|
},
|
|
785
819
|
null,
|
|
@@ -811,6 +845,11 @@ function main(argv: string[]): number {
|
|
|
811
845
|
` frequency: ${summary.frequency_gap} gap · ${summary.frequency_unclassified} unclassified ` +
|
|
812
846
|
`(kernel — block_kernel_rule_writes denies the field)`,
|
|
813
847
|
);
|
|
848
|
+
lines.push(
|
|
849
|
+
` undeclared ${summary.undeclared} splits: ${summary.kernel_denied} kernel-denied · ` +
|
|
850
|
+
`${summary.observer} observer · ${summary.carrier_less} carrier-less — ` +
|
|
851
|
+
`the observer set is the reachable population`,
|
|
852
|
+
);
|
|
814
853
|
// The denominator is published WITH its frame, and it is the only sanctioned
|
|
815
854
|
// source for that number: `check_enforcement_denominator` reds when a
|
|
816
855
|
// tracked doc carries an enforcement count this resolver did not produce.
|
|
@@ -280,6 +280,7 @@ export function main(argv: readonly string[]): number {
|
|
|
280
280
|
// reaches another section, another era file, or `docs/archive/`. That is
|
|
281
281
|
// what keeps eighteen historical marker lines from turning this into a
|
|
282
282
|
// permanent red on every future release.
|
|
283
|
+
const derived = derive_categories(span);
|
|
283
284
|
const drafts = stale_draft_labels(curated);
|
|
284
285
|
if (drafts.length > 0) {
|
|
285
286
|
process.stderr.write(
|
|
@@ -292,9 +293,24 @@ export function main(argv: readonly string[]): number {
|
|
|
292
293
|
' historical sections carrying the same marker are out of scope and do not ' +
|
|
293
294
|
'block this release.\n',
|
|
294
295
|
);
|
|
296
|
+
// The evidence, not just the verdict. The draft line cites SHAs and a
|
|
297
|
+
// deriving reason; what a releaser needs in order to write the real
|
|
298
|
+
// claim is the SUBJECT behind each SHA, and looking eleven of them up
|
|
299
|
+
// by hand is the friction that made this refusal cheaper to ignore
|
|
300
|
+
// than to satisfy across five releases. The `_none_` branch below has
|
|
301
|
+
// printed its evidence since it was built; this one now matches it.
|
|
302
|
+
for (const label of drafts) {
|
|
303
|
+
const hits = derived[label] ?? [];
|
|
304
|
+
if (hits.length === 0) {
|
|
305
|
+
continue;
|
|
306
|
+
}
|
|
307
|
+
process.stderr.write(` - **${label}:** derived from\n`);
|
|
308
|
+
for (const e of hits) {
|
|
309
|
+
process.stderr.write(` ${e}\n`);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
295
312
|
return 1;
|
|
296
313
|
}
|
|
297
|
-
const derived = derive_categories(span);
|
|
298
314
|
const contradictions = highlight_contradictions(curated, derived);
|
|
299
315
|
if (contradictions.length === 0) {
|
|
300
316
|
process.stdout.write(`✅ curated head plausible for ${version} (span ${from}..${to})\n`);
|