@event4u/agent-config 14.6.0 → 14.7.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/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +260 -7
- package/README.md +1 -1
- package/dist/agent-src/commands/analyze/inbox.md +264 -10
- package/dist/agent-src/commands/analyze.md +1 -1
- package/dist/agent-src/commands/roadmap/process-full.md +116 -30
- package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +31 -0
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +135 -104
- package/dist/agent-src/rules/context-hygiene.md +2 -0
- package/dist/agent-src/rules/decision-revisit-gate.md +3 -0
- package/dist/agent-src/rules/fix-what-you-see.md +108 -0
- package/dist/agent-src/rules/no-roadmap-references.md +0 -5
- package/dist/agent-src/rules/recurring-criticism.md +110 -0
- package/dist/agent-src/rules/roadmap-progress-sync.md +1 -1
- package/dist/agent-src/rules/rule-type-governance.md +0 -2
- package/dist/agent-src/rules/self-repair-loop.md +17 -0
- package/dist/agent-src/rules/skill-quality.md +0 -2
- package/dist/agent-src/rules/source-confidentiality.md +37 -7
- package/dist/agent-src/scripts/archival_sweep.ts +117 -0
- package/dist/agent-src/scripts/archive_completed_roadmaps.ts +19 -3
- package/dist/agent-src/scripts/gate_budget.ts +282 -0
- package/dist/agent-src/scripts/gate_execute.ts +72 -31
- package/dist/agent-src/scripts/roadmap_gates.ts +74 -3
- package/dist/agent-src/scripts/update_roadmap_progress.ts +251 -7
- package/dist/agent-src/skills/ai-council/SKILL.md +48 -807
- package/dist/agent-src/skills/ai-council/references/advanced-modes.md +320 -0
- package/dist/agent-src/skills/ai-council/references/cost-and-redaction.md +99 -0
- package/dist/agent-src/skills/ai-council/references/execution-modes.md +162 -0
- package/dist/agent-src/skills/ai-council/references/output-and-synthesis.md +125 -0
- package/dist/agent-src/skills/ai-council/references/procedure.md +143 -0
- package/dist/agent-src/skills/quality-tools/SKILL.md +34 -326
- package/dist/agent-src/skills/quality-tools/references/js-ts-tools.md +113 -0
- package/dist/agent-src/skills/quality-tools/references/php-tools.md +222 -0
- package/dist/agent-src/skills/roadmap-management/SKILL.md +15 -409
- package/dist/agent-src/skills/roadmap-management/references/archival.md +226 -0
- package/dist/agent-src/skills/roadmap-management/references/authoring.md +107 -0
- package/dist/agent-src/skills/roadmap-management/references/dashboard.md +47 -0
- package/dist/agent-src/skills/roadmap-management/references/lifecycle.md +58 -0
- package/dist/agent-src/skills/skill-writing/SKILL.md +34 -570
- package/dist/agent-src/skills/skill-writing/references/procedure.md +275 -0
- package/dist/agent-src/skills/skill-writing/references/read-only-scripts.md +18 -0
- package/dist/agent-src/skills/skill-writing/references/section-patterns.md +298 -0
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/roadmaps.md +45 -2
- package/dist/agent-src/templates/scripts/telemetry/flush_sender.mjs +163 -0
- package/dist/agent-src/templates/scripts/telemetry/remote.ts +160 -7
- package/dist/agent-src/templates/scripts/telemetry/transport.ts +169 -0
- package/dist/cli/registry.js +1 -1
- package/dist/cli/registry.js.map +1 -1
- package/dist/cli-delegate/chunk-2GNWGMAL.js +172 -0
- package/dist/cli-delegate/{chunk-RLN73PR5.js → chunk-4VR4ORQ6.js} +10 -7
- package/dist/cli-delegate/chunk-6EOCNQAM.js +402 -0
- package/dist/cli-delegate/{chunk-XURJ4AQC.js → chunk-74E3TKWV.js} +381 -280
- package/dist/cli-delegate/{chunk-3UCJWMMP.js → chunk-7F3VYSM2.js} +4 -4
- package/dist/cli-delegate/{chunk-BKO2AZ7Z.js → chunk-B2ERU2VA.js} +1 -1
- package/dist/cli-delegate/{chunk-NXFWFAYV.js → chunk-G23AT6GD.js} +1 -0
- package/dist/cli-delegate/{chunk-63WSP6YZ.js → chunk-GJ5BVHXM.js} +72 -165
- package/dist/cli-delegate/{chunk-P6LQDIWK.js → chunk-JZ4NR2TW.js} +338 -0
- package/dist/cli-delegate/chunk-MWRD5YOH.js +100 -0
- package/dist/cli-delegate/{chunk-GRRPEPRN.js → chunk-T7L2QK3K.js} +24 -5
- package/dist/cli-delegate/{chunk-EVTY7ISR.js → chunk-YM4GZDJG.js} +9 -1
- package/dist/cli-delegate/cmd_conformance.js +459 -709
- package/dist/cli-delegate/cmd_doctor.js +6 -6
- package/dist/cli-delegate/cmd_explain.js +1 -1
- package/dist/cli-delegate/cmd_export.js +7 -6
- package/dist/cli-delegate/cmd_handoff.js +6 -6
- package/dist/cli-delegate/cmd_packs_active.js +1 -1
- package/dist/cli-delegate/cmd_preflight.js +2 -2
- package/dist/cli-delegate/cmd_prune.js +7 -6
- package/dist/cli-delegate/cmd_session_recycle.js +840 -30
- package/dist/cli-delegate/cmd_settings_migrate.js +7 -6
- package/dist/cli-delegate/cmd_settings_set.js +1 -1
- package/dist/cli-delegate/cmd_sync.js +7 -6
- package/dist/cli-delegate/cmd_uninstall.js +9 -7
- 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 +7 -6
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +68 -25
- 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 +2901 -2053
- package/dist/install/claudePathsPlan.js +187 -0
- package/dist/install/claudePathsPlan.js.map +1 -0
- package/dist/install/hostLayerFingerprint.js +136 -0
- package/dist/install/hostLayerFingerprint.js.map +1 -0
- package/dist/install/install.mjs +553 -425
- package/dist/install/partitionEligibility.js +276 -0
- package/dist/install/partitionEligibility.js.map +1 -0
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +1744 -1191
- package/dist/router.json +1 -1
- package/dist/scripts/_lib/agent_src.js +41 -0
- package/dist/scripts/_lib/agent_src.js.map +1 -1
- package/dist/scripts/_lib/install_layout.js +83 -0
- package/dist/scripts/_lib/install_layout.js.map +1 -0
- package/dist/scripts/_lib/installed_lock.js +444 -0
- package/dist/scripts/_lib/installed_lock.js.map +1 -0
- package/dist/scripts/condense.js +13 -164
- package/dist/scripts/condense.js.map +1 -1
- package/dist/server/schemas/settings.js +4 -0
- package/dist/server/schemas/settings.js.map +1 -1
- package/docs/contracts/settings-classes.md +12 -6
- package/docs/guidelines/agent-infra/agent-interaction-and-decision-quality.md +8 -3
- package/docs/guidelines/agent-infra/context-hygiene-mechanics.md +26 -0
- package/docs/guidelines/agent-infra/memory-access.md +17 -0
- package/docs/guidelines/agent-infra/recurring-criticism-mechanics.md +96 -0
- package/package.json +1 -1
- package/src/agent-src/scripts/archival_sweep.ts +117 -0
- package/src/agent-src/scripts/archive_completed_roadmaps.ts +19 -3
- package/src/agent-src/scripts/gate_budget.ts +282 -0
- package/src/agent-src/scripts/gate_execute.ts +72 -31
- package/src/agent-src/scripts/roadmap_gates.ts +74 -3
- package/src/agent-src/scripts/update_roadmap_progress.ts +251 -7
- package/src/agent-src/templates/scripts/telemetry/flush_sender.mjs +163 -0
- package/src/agent-src/templates/scripts/telemetry/remote.ts +160 -7
- package/src/agent-src/templates/scripts/telemetry/transport.ts +169 -0
- package/src/config/agent-settings.template.yml +27 -2
- package/src/config/ci-local-parity.yml +18 -0
- package/src/config/estate-count-budget.json +339 -3
- package/src/config/gate-violation-baselines.json +41 -41
- package/src/config/rule-activation-census.json +14 -6
- package/src/config/rule-stub-ceilings.json +19 -6
- package/src/install/claudePathsPlan.ts +196 -0
- package/src/install/hostLayerFingerprint.ts +145 -0
- package/src/install/partitionEligibility.ts +325 -0
- package/src/scripts/_cli/cmd_session_recycle.ts +9 -1
- package/src/scripts/_dispatch.bash +6 -1
- package/src/scripts/_lib/ac_heading.ts +30 -0
- package/src/scripts/_lib/agent_src.ts +42 -0
- package/src/scripts/_lib/bench_ab_pinned_repo.ts +162 -0
- package/src/scripts/_lib/bench_ab_workspace.ts +10 -1
- package/src/scripts/_lib/envelope_grounding.ts +38 -8
- package/src/scripts/_lib/installed_lock.ts +50 -5
- package/src/scripts/_lib/md_section.ts +129 -0
- package/src/scripts/_lib/scope_guard.sh +26 -3
- package/src/scripts/_lib/self_repair.ts +19 -0
- package/src/scripts/_lib/self_repair_class_b.ts +171 -0
- package/src/scripts/ai_council/cli_help.ts +55 -0
- package/src/scripts/before_complete_hook.ts +153 -28
- package/src/scripts/bench_ab_v2_complexity.ts +27 -7
- package/src/scripts/check_references.ts +60 -0
- package/src/scripts/check_release_published.ts +32 -11
- package/src/scripts/check_single_delivery.ts +59 -15
- package/src/scripts/ci_settle.ts +170 -0
- package/src/scripts/condense.ts +20 -170
- package/src/scripts/council_cli.ts +3 -3
- package/src/scripts/dispatch_r2_reviewer.ts +6 -14
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +77 -14
- package/src/scripts/hooks/block_no_verify.ts +61 -10
- package/src/scripts/hooks/block_unauthorized_git.ts +1 -1
- package/src/scripts/hooks/concern_registry.ts +4 -0
- package/src/scripts/hooks/rtk_wrap_hook.ts +8 -3
- package/src/scripts/hooks/run_continuation_hook.ts +8 -5
- package/src/scripts/hooks/ship_diff_volume_hook.ts +81 -15
- package/src/scripts/hooks/source_first_gate_hook.ts +464 -0
- package/src/scripts/hooks/state_io.ts +782 -20
- package/src/scripts/hooks/subagent_ledger_hook.ts +44 -15
- package/src/scripts/hooks/telemetry_flush_hook.ts +139 -0
- package/src/scripts/hooks/telemetry_self_repair.ts +128 -0
- package/src/scripts/hooks/telemetry_usage_hook.ts +22 -4
- package/src/scripts/hooks/turn_end_gate_hook.ts +81 -15
- package/src/scripts/install.ts +16 -11
- package/src/scripts/language_mirror_hook.ts +561 -25
- package/src/scripts/lint_framework_leakage_allowlist.json +2 -2
- package/src/scripts/lint_plan_risk_register.ts +4 -3
- package/src/scripts/lint_skill_router_head.ts +4 -4
- package/src/scripts/mcp_server/tools.ts +2 -2
- package/src/scripts/new_roadmap.ts +136 -0
- package/src/scripts/pack_mcp_content.ts +20 -5
- package/src/scripts/release.ts +37 -38
- package/src/scripts/report_layer_overlap.ts +6 -0
- package/src/scripts/self_repair_hook.ts +37 -5
- package/src/scripts/session_register_hook.ts +11 -0
- package/src/scripts/skill_usage_collect.ts +11 -1
- package/src/scripts/skill_usage_report.ts +278 -8
- package/src/scripts/sync_pr_branch.ts +7 -0
- package/src/server/schemas/settings.ts +8 -0
- package/dist/cli-delegate/chunk-EJITJBJX.js +0 -172
- package/dist/cli-delegate/chunk-PZWRPRWP.js +0 -38
- /package/dist/cli-delegate/{chunk-RYNADUFG.js → chunk-LWTYTX6F.js} +0 -0
|
@@ -88,9 +88,9 @@
|
|
|
88
88
|
"reason": "Quoted anti-example ('❌ Describing how Laravel middleware works') — the line teaches what NOT to write."
|
|
89
89
|
},
|
|
90
90
|
{
|
|
91
|
-
"file": "src/skills/skill-writing/
|
|
91
|
+
"file": "src/skills/skill-writing/references/procedure.md",
|
|
92
92
|
"anchor": "Use when creating Laravel middleware for request filtering",
|
|
93
|
-
"reason": "Quoted description examples + the 'too-broad skill (Laravel skill)' anti-pattern — meta content."
|
|
93
|
+
"reason": "Quoted description examples + the 'too-broad skill (Laravel skill)' anti-pattern — meta content. Repointed 2026-08-20: the K6 router-head retrofit moved the quoted description examples out of the head into references/procedure.md, so the anchor no longer matched its file and the entry exempted nothing. The content is unchanged and still meta."
|
|
94
94
|
},
|
|
95
95
|
{
|
|
96
96
|
"file": "src/skills/supply-chain-intake/SKILL.md",
|
|
@@ -39,6 +39,7 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
|
39
39
|
|
|
40
40
|
import { parse as parseYaml } from 'yaml';
|
|
41
41
|
|
|
42
|
+
import { isAcceptanceCriteriaHeading } from './_lib/ac_heading.js';
|
|
42
43
|
import { workspaceIdentity } from './_lib/git_common_dir.js';
|
|
43
44
|
import { gitEnv } from './_lib/git_env.js';
|
|
44
45
|
import { splitMarkdownRow } from './_lib/md_table.js';
|
|
@@ -52,7 +53,7 @@ import { assertScanned, DeadScopeError } from './_lib/scan_scope.js';
|
|
|
52
53
|
*/
|
|
53
54
|
export const RISK_REGISTER_GATE_ACTIVATION = '2026-08-04';
|
|
54
55
|
|
|
55
|
-
const MARKER_RE =
|
|
56
|
+
export const MARKER_RE =
|
|
56
57
|
/^<!--\s*risk-review:\s*v1\s*\|\s*reviewed:\s*(\d{4}-\d{2}-\d{2})\s*\|\s*reviewer:\s*(.+?)\s*-->\s*$/;
|
|
57
58
|
const HONEST_NULL_RE = /^\*\*Honest-null:\*\*(.*)$/;
|
|
58
59
|
const CHECKBOX_RE = /^\s*- \[( |x|~|-)\]/;
|
|
@@ -72,7 +73,7 @@ export interface PlanFeatures {
|
|
|
72
73
|
phaseHeadings: string[];
|
|
73
74
|
/** Total count of deliverable checkbox lines (state-insensitive). */
|
|
74
75
|
checkboxCount: number;
|
|
75
|
-
/** sha256 of the
|
|
76
|
+
/** sha256 of the acceptance-criteria section body (heading matched per `_lib/ac_heading`; checkbox state normalized). */
|
|
76
77
|
acHash: string;
|
|
77
78
|
}
|
|
78
79
|
|
|
@@ -115,7 +116,7 @@ export function extractFeatures(text: string): PlanFeatures {
|
|
|
115
116
|
if (CHECKBOX_RE.test(entry.line)) {
|
|
116
117
|
checkboxCount += 1;
|
|
117
118
|
}
|
|
118
|
-
if (
|
|
119
|
+
if (isAcceptanceCriteriaHeading(entry.line)) {
|
|
119
120
|
acStart = i;
|
|
120
121
|
}
|
|
121
122
|
}
|
|
@@ -59,10 +59,10 @@ export const MODE_BODY_DIRS: readonly string[] = ['tasks', 'references'];
|
|
|
59
59
|
* Measured, not guessed. REMOVE entries as skills are restructured; never add.
|
|
60
60
|
*/
|
|
61
61
|
export const GRANDFATHERED: readonly string[] = [
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
62
|
+
// Emptied 2026-08-20: all four seeded entries were restructured into router
|
|
63
|
+
// heads (entry head + `references/` mode bodies) under the published K6 cap.
|
|
64
|
+
// Shrink-only means this list may never grow again — a new oversized
|
|
65
|
+
// monolith fails the gate instead of joining it.
|
|
66
66
|
];
|
|
67
67
|
|
|
68
68
|
export interface Finding {
|
|
@@ -669,7 +669,7 @@ async function _roadmapProgressHandler(
|
|
|
669
669
|
};
|
|
670
670
|
}
|
|
671
671
|
const roadmaps = urp.collect(roadmapRoot);
|
|
672
|
-
const content = urp.render(roadmaps, urp.collect_bundles(root));
|
|
672
|
+
const content = urp.render(roadmaps, urp.collect_bundles(root), roadmapRoot);
|
|
673
673
|
const stepsDone = roadmaps.reduce((s, r) => s + r.done, 0);
|
|
674
674
|
const stepsTotal = roadmaps.reduce((s, r) => s + r.total_active, 0);
|
|
675
675
|
if (!dryRun) {
|
|
@@ -719,7 +719,7 @@ async function _roadmapArchiveHandler(
|
|
|
719
719
|
const roadmaps = urp.collect(roadmapRoot);
|
|
720
720
|
fs.writeFileSync(
|
|
721
721
|
path.join(root, 'agents', 'roadmaps-progress.md'),
|
|
722
|
-
urp.render(roadmaps, urp.collect_bundles(root)),
|
|
722
|
+
urp.render(roadmaps, urp.collect_bundles(root), roadmapRoot),
|
|
723
723
|
'utf-8',
|
|
724
724
|
);
|
|
725
725
|
dashboardRegenerated = true;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* Emit a roadmap skeleton that passes every roadmap gate unedited.
|
|
4
|
+
*
|
|
5
|
+
* WHY THIS EXISTS. Four authoring conventions are enforced by four different
|
|
6
|
+
* gates and documented in prose an author has to already know to look for:
|
|
7
|
+
*
|
|
8
|
+
* 1. `complexity:` is a two-value enum — `lightweight` | `structural`.
|
|
9
|
+
* Measured 2026-08-20 across 88 roadmaps: six DIFFERENT invented values
|
|
10
|
+
* were in the tree (`bounded`, `medium`, `moderate`, `small`, `standard`),
|
|
11
|
+
* one of them on the active side and reddening the trunk, seven more in
|
|
12
|
+
* `later/` where the gate does not scan and which would red on the day
|
|
13
|
+
* they are reactivated.
|
|
14
|
+
* 2. The acceptance heading is matched CASE-INSENSITIVELY and without an end
|
|
15
|
+
* anchor — one predicate, `_lib/ac_heading.ts`, shared by the R1 gate and
|
|
16
|
+
* the R2 dispatcher. It was not always: an end-anchored, case-sensitive
|
|
17
|
+
* copy made 10 of 22 roadmaps writing `Acceptance criteria` invisible to
|
|
18
|
+
* the extractor, and a third copy in `lint_plan_risk_register` kept both
|
|
19
|
+
* faults until 2026-08-20, hashing the empty string for 8 of the 32 ready
|
|
20
|
+
* roadmaps while the gate exited 0. The skeleton still emits the
|
|
21
|
+
* capitalised form: it is the shape every reader already recognises, and
|
|
22
|
+
* nothing now depends on the case.
|
|
23
|
+
* 3. The Risk Register needs its `<!-- risk-review: … -->` marker as the
|
|
24
|
+
* first non-blank line of the section.
|
|
25
|
+
* 4. `Risk type` is a two-value enum — `product` | `implementation`. The
|
|
26
|
+
* natural third word (`process`) hard-fails at pre-push.
|
|
27
|
+
*
|
|
28
|
+
* Every one of those is cheap to satisfy up front and costs a full gate round
|
|
29
|
+
* to discover. This command satisfies them by construction.
|
|
30
|
+
*
|
|
31
|
+
* The skeleton is deliberately MINIMAL: one phase, one step, one risk row. It
|
|
32
|
+
* is a starting point that is green, not a template to fill in blindly — the
|
|
33
|
+
* content is the author's, the shape is not worth rediscovering.
|
|
34
|
+
*
|
|
35
|
+
* Usage: ./scripts-run src/scripts/new_roadmap <slug> [--structural] [--stdout]
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
import * as fs from 'node:fs';
|
|
39
|
+
import * as path from 'node:path';
|
|
40
|
+
|
|
41
|
+
/** Today, as the risk-review marker wants it. */
|
|
42
|
+
function today(): string {
|
|
43
|
+
return new Date().toISOString().slice(0, 10);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** `road to X` from a kebab slug, for the H1. */
|
|
47
|
+
function titleOf(slug: string): string {
|
|
48
|
+
return slug.replace(/-/g, ' ');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function skeleton(slug: string, complexity: 'lightweight' | 'structural', date: string): string {
|
|
52
|
+
return `---
|
|
53
|
+
complexity: ${complexity}
|
|
54
|
+
status: draft
|
|
55
|
+
execution:
|
|
56
|
+
mode: phase-checkpoints
|
|
57
|
+
---
|
|
58
|
+
# Road to ${titleOf(slug)}
|
|
59
|
+
|
|
60
|
+
> **Source:** replace this with where the finding came from — a measurement, a
|
|
61
|
+
> review, an incident. A roadmap whose origin is not stated cannot be checked
|
|
62
|
+
> against it later.
|
|
63
|
+
|
|
64
|
+
## Goal
|
|
65
|
+
|
|
66
|
+
One paragraph: what is true when this is finished, phrased so someone else
|
|
67
|
+
could tell whether it happened.
|
|
68
|
+
|
|
69
|
+
## Phase 1 — <name the first coherent slice>
|
|
70
|
+
|
|
71
|
+
- [ ] **1.1 <the step, as an imperative>.** What changes, and why it is not
|
|
72
|
+
already the case.
|
|
73
|
+
verify: the check that proves it — a command, a test, an observable
|
|
74
|
+
state. Never "looks right".
|
|
75
|
+
|
|
76
|
+
## Risk Register
|
|
77
|
+
<!-- risk-review: v1 | reviewed: ${date} | reviewer: claude/host -->
|
|
78
|
+
|
|
79
|
+
| Rank | Item | Risk type | Description | Mitigation | Anchored under |
|
|
80
|
+
|------|------|-----------|-------------|------------|----------------|
|
|
81
|
+
| 1 | <the way this roadmap most plausibly fails> | implementation | What goes wrong, concretely | What makes it not happen, or what catches it | Phase 1 — <name the first coherent slice> |
|
|
82
|
+
|
|
83
|
+
## Acceptance Criteria
|
|
84
|
+
|
|
85
|
+
- [ ] AC-1 — <the residual state, not the activity>. Phrase it on what is true
|
|
86
|
+
afterwards, so a step that ran but achieved nothing cannot satisfy it.
|
|
87
|
+
`;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function main(argv: readonly string[]): number {
|
|
91
|
+
const args = argv.filter((a) => !a.startsWith('--'));
|
|
92
|
+
const structural = argv.includes('--structural');
|
|
93
|
+
const toStdout = argv.includes('--stdout');
|
|
94
|
+
const slug = args[0];
|
|
95
|
+
|
|
96
|
+
if (slug === undefined || slug.length === 0) {
|
|
97
|
+
process.stderr.write(
|
|
98
|
+
'usage: new_roadmap <slug> [--structural] [--stdout]\n' +
|
|
99
|
+
' <slug> kebab-case, without the road-to- prefix\n' +
|
|
100
|
+
' --structural tag structural instead of lightweight (no line/phase cap)\n' +
|
|
101
|
+
' --stdout print instead of writing the file\n',
|
|
102
|
+
);
|
|
103
|
+
return 2;
|
|
104
|
+
}
|
|
105
|
+
if (!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(slug)) {
|
|
106
|
+
process.stderr.write(`new_roadmap: slug must be kebab-case, got '${slug}'\n`);
|
|
107
|
+
return 2;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const body = skeleton(slug, structural ? 'structural' : 'lightweight', today());
|
|
111
|
+
if (toStdout) {
|
|
112
|
+
process.stdout.write(body);
|
|
113
|
+
return 0;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const rel = path.join('agents', 'roadmaps', `road-to-${slug}.md`);
|
|
117
|
+
if (fs.existsSync(rel)) {
|
|
118
|
+
process.stderr.write(`new_roadmap: ${rel} already exists — refusing to overwrite\n`);
|
|
119
|
+
return 1;
|
|
120
|
+
}
|
|
121
|
+
fs.mkdirSync(path.dirname(rel), { recursive: true });
|
|
122
|
+
fs.writeFileSync(rel, body, 'utf-8');
|
|
123
|
+
process.stdout.write(
|
|
124
|
+
`✅ wrote ${rel}\n` +
|
|
125
|
+
' It passes the roadmap gates as emitted. Adding a `### blocker:` entry or\n' +
|
|
126
|
+
' flipping status to `ready` grows the estate — check_estate_count wants the\n' +
|
|
127
|
+
' baseline raised with a reason in the same commit.\n',
|
|
128
|
+
);
|
|
129
|
+
return 0;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (process.argv[1] !== undefined && import.meta.url.endsWith(path.basename(process.argv[1]))) {
|
|
133
|
+
process.exitCode = main(process.argv.slice(2));
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export { main, titleOf, today };
|
|
@@ -41,11 +41,26 @@ import { scan_contexts, scan_guidelines, scan_rules } from './mcp_server/resourc
|
|
|
41
41
|
|
|
42
42
|
const SCHEMA_VERSION = 1;
|
|
43
43
|
const PACKER_VERSION = '1.0.0';
|
|
44
|
-
// Worker bundle is the compact JSON; gzipped copy lives in R2.
|
|
45
|
-
// condensed-bundle limit
|
|
46
|
-
//
|
|
47
|
-
// the
|
|
48
|
-
|
|
44
|
+
// Worker bundle is the compact JSON; gzipped copy lives in R2. This constant is
|
|
45
|
+
// a PROXY for Cloudflare's condensed-bundle limit (3 MB free / 10 MB paid) — it
|
|
46
|
+
// hard-fails early so the build dies before the Worker upload does. Because it is
|
|
47
|
+
// a proxy, the number that matters is the gz one, and both are restated here as
|
|
48
|
+
// MEASURED values rather than remembered ones.
|
|
49
|
+
//
|
|
50
|
+
// Measured 2026-08-20 on origin/main (770 entries): uncondensed 5,230,537 B,
|
|
51
|
+
// gz 1,793,879 B. So the real constraint sits at 57 % of the free tier with
|
|
52
|
+
// ~1.2 MB of room, while the old 5 MiB proxy had 12,343 B of headroom — a 0.24 %
|
|
53
|
+
// margin on trunk, which made ANY addition above ~12 KB to rules, guidelines or
|
|
54
|
+
// contexts fail here regardless of merit. Raised to 6 MiB, deliberately well
|
|
55
|
+
// above the measurement: a cap pinned just over the current figure reds on the
|
|
56
|
+
// next commit and teaches people to raise it again.
|
|
57
|
+
//
|
|
58
|
+
// The prior comment claimed "778 KB gz today (438 entries)". That was stale by
|
|
59
|
+
// 2.3x on size and 332 entries — the reason the proxy drifted into a blocker
|
|
60
|
+
// without anyone noticing was that its own justification was never re-measured.
|
|
61
|
+
// If this needs raising again, re-measure BOTH numbers and replace them here;
|
|
62
|
+
// the gz figure against 3 MB is the one that decides whether there is a problem.
|
|
63
|
+
const MAX_UNCONDENSED_BYTES = 6 * 1024 * 1024;
|
|
49
64
|
|
|
50
65
|
/** Sentinel for the early-exit paths (`raise SystemExit(n)` in Python). */
|
|
51
66
|
class SystemExit extends Error {
|
package/src/scripts/release.ts
CHANGED
|
@@ -2475,55 +2475,54 @@ export function nothing_to_release_ci(
|
|
|
2475
2475
|
|
|
2476
2476
|
const _RELEASE_BRANCH_RE = /^release\/(\d+\.\d+\.\d+)$/;
|
|
2477
2477
|
|
|
2478
|
+
/** `package.json`'s `version`, or null when unreadable, not JSON, or key-less. */
|
|
2479
|
+
function _package_version_or_null(): string | null {
|
|
2480
|
+
try {
|
|
2481
|
+
const data = JSON.parse(fs.readFileSync(PACKAGE_JSON, 'utf-8')) as Record<string, unknown>;
|
|
2482
|
+
return 'version' in data ? (data['version'] as string) : null;
|
|
2483
|
+
} catch {
|
|
2484
|
+
return null;
|
|
2485
|
+
}
|
|
2486
|
+
}
|
|
2487
|
+
|
|
2488
|
+
/** Observations `_detect_in_flight_target` reads; injected by its tests. */
|
|
2489
|
+
export interface InFlightProbes {
|
|
2490
|
+
head_branch?: () => string;
|
|
2491
|
+
package_version?: () => string | null;
|
|
2492
|
+
/** True when the tag is ON THE REMOTE — never merely local. */
|
|
2493
|
+
tag_published?: (tag: string) => boolean;
|
|
2494
|
+
}
|
|
2495
|
+
|
|
2478
2496
|
/**
|
|
2479
|
-
*
|
|
2480
|
-
*
|
|
2481
|
-
*
|
|
2482
|
-
*
|
|
2483
|
-
*
|
|
2484
|
-
*
|
|
2485
|
-
* `release
|
|
2486
|
-
*
|
|
2487
|
-
* Why not the branch set: merged release branches are frequently left
|
|
2488
|
-
* undeleted on the remote, so "highest existing release/* branch" can resolve
|
|
2489
|
-
* to an OLD, already-published version (e.g. picking 5.4.0 while 5.8.0 is the
|
|
2490
|
-
* real in-flight target) and tag a downgrade. The package.json version cannot
|
|
2491
|
-
* lie that way — it is the version main currently claims to be, and an
|
|
2492
|
-
* untagged claim is exactly an incomplete release.
|
|
2493
|
-
*
|
|
2494
|
-
* Resolution order:
|
|
2495
|
-
* 1. If HEAD is on a `release/X.Y.Z` branch, that explicit checkout wins.
|
|
2496
|
-
* 2. Else: read `package.json` version `V`. If tag `V` does not exist
|
|
2497
|
-
* (local or remote), `V` is the in-flight target. If it is already
|
|
2498
|
-
* tagged, the release is complete → return null (regular bump path).
|
|
2499
|
-
*
|
|
2500
|
-
* Stale `release/*` branches are never used for version detection.
|
|
2497
|
+
* In-flight release target: `package.json` claims `V` while no PUBLISHED tag
|
|
2498
|
+
* `V` exists, so the publish step never completed. HEAD on `release/X.Y.Z`
|
|
2499
|
+
* wins first; stale `release/*` branches are never consulted (a merged one
|
|
2500
|
+
* left undeleted can tag a downgrade). PUBLISHED means on the REMOTE, because
|
|
2501
|
+
* publish-npm.yml triggers on `push: tags:`. Why not a local tag, and the
|
|
2502
|
+
* 14.6.0 release that stranded on the old form: see
|
|
2503
|
+
* `tests/scripts/release.test.ts` § _detect_in_flight_target.
|
|
2501
2504
|
*/
|
|
2502
|
-
function _detect_in_flight_target(): string | null {
|
|
2503
|
-
const
|
|
2504
|
-
|
|
2505
|
+
function _detect_in_flight_target(probes: InFlightProbes = {}): string | null {
|
|
2506
|
+
const head_branch =
|
|
2507
|
+
probes.head_branch ?? (() => git(['rev-parse', '--abbrev-ref', 'HEAD'], { capture: true }));
|
|
2508
|
+
const package_version = probes.package_version ?? _package_version_or_null;
|
|
2509
|
+
const tag_published = probes.tag_published ?? _tag_exists_remote;
|
|
2510
|
+
|
|
2511
|
+
const m = _RELEASE_BRANCH_RE.exec(head_branch());
|
|
2505
2512
|
if (m) {
|
|
2506
2513
|
return m[1] as string;
|
|
2507
2514
|
}
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
const data = JSON.parse(fs.readFileSync(PACKAGE_JSON, 'utf-8')) as Record<string, unknown>;
|
|
2512
|
-
if (!('version' in data)) {
|
|
2513
|
-
return null; // KeyError analogue.
|
|
2514
|
-
}
|
|
2515
|
-
version = data['version'] as string;
|
|
2516
|
-
} catch {
|
|
2517
|
-
return null; // OSError / JSONDecodeError analogue.
|
|
2515
|
+
const version = package_version();
|
|
2516
|
+
if (version === null) {
|
|
2517
|
+
return null;
|
|
2518
2518
|
}
|
|
2519
2519
|
try {
|
|
2520
2520
|
parse_version(version);
|
|
2521
2521
|
} catch {
|
|
2522
2522
|
return null;
|
|
2523
2523
|
}
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
if (_tag_exists_local(version) || _tag_exists_remote(version)) {
|
|
2524
|
+
// A PUBLISHED tag is a completed release; a local-only tag is not.
|
|
2525
|
+
if (tag_published(version)) {
|
|
2527
2526
|
return null;
|
|
2528
2527
|
}
|
|
2529
2528
|
return version;
|
|
@@ -26,6 +26,12 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
|
26
26
|
|
|
27
27
|
import { warnLayerOverlap } from './_lib/layer_overlap_notice.js';
|
|
28
28
|
|
|
29
|
+
// ledger-exempt: this is a REPORTER, not a gate — it always exits 0 by construction
|
|
30
|
+
// (see the docstring above), so there is no verdict for a per-target ledger to
|
|
31
|
+
// account for. `_lib/gate_ledger` records why a gate passed over a target; a script
|
|
32
|
+
// that cannot fail passes over nothing. The advisory-only property is asserted by the
|
|
33
|
+
// task step that calls it, not by this marker.
|
|
34
|
+
|
|
29
35
|
const _HERE = fileURLToPath(import.meta.url);
|
|
30
36
|
const REPO_ROOT = path.resolve(path.dirname(_HERE), '..', '..');
|
|
31
37
|
|
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
} from './_lib/self_repair.js';
|
|
39
39
|
import { openRecords, upsertFinding } from './_lib/self_repair_store.js';
|
|
40
40
|
import { readHookStdin } from './hooks/hook_stdin.js';
|
|
41
|
+
import { emitDefectShadow } from './hooks/telemetry_self_repair.js';
|
|
41
42
|
|
|
42
43
|
const EXIT_ALLOW = 0;
|
|
43
44
|
|
|
@@ -130,11 +131,28 @@ export function readTurn(transcriptPath: string, pinned: 'de' | 'en' | null): Tu
|
|
|
130
131
|
return { prompt, reply, toolCommands, pinnedLanguage: pinned };
|
|
131
132
|
}
|
|
132
133
|
|
|
133
|
-
/**
|
|
134
|
-
|
|
134
|
+
/**
|
|
135
|
+
* The queue line injected at prompt time when records are waiting.
|
|
136
|
+
*
|
|
137
|
+
* `occurrences` is the newest record's own repeat counter, and it is in the line
|
|
138
|
+
* because the store has always counted while the model never saw the number: a
|
|
139
|
+
* recurring defect increments one record instead of adding a queue entry, so
|
|
140
|
+
* `count` stays flat and the recurrence is invisible. Above 1 it is the only
|
|
141
|
+
* deterministic "this came back" signal an agent gets, which is what makes
|
|
142
|
+
* `decision-revisit-gate` § Recurrence executable rather than aspirational.
|
|
143
|
+
* Omitted at 1 — a first sighting has nothing to say.
|
|
144
|
+
*/
|
|
145
|
+
export function buildQueueLine(count: number, newest: string, occurrences = 1): string {
|
|
146
|
+
const repeat =
|
|
147
|
+
occurrences > 1
|
|
148
|
+
? ` The newest record has recurred ${occurrences} time(s): the earlier ` +
|
|
149
|
+
`disposition did not hold, so per decision-revisit-gate § Recurrence ` +
|
|
150
|
+
`reopen it and name which assumption broke — resolve on evidence, ` +
|
|
151
|
+
`never on the repetition count.`
|
|
152
|
+
: '';
|
|
135
153
|
return (
|
|
136
154
|
`<self-repair-queue>${count} open agent-config defect record(s) ` +
|
|
137
|
-
`(newest: ${newest})
|
|
155
|
+
`(newest: ${newest}).${repeat} These are defects in the AGENT CONFIG, not in this ` +
|
|
138
156
|
`project. Per the self-repair rule: analyse the newest record, author the ` +
|
|
139
157
|
`fix against agent-config, and prepare the release — the outward step ` +
|
|
140
158
|
`(push + PR, or an issue) still needs the user's word this turn. ` +
|
|
@@ -185,7 +203,17 @@ export function main(): number {
|
|
|
185
203
|
|
|
186
204
|
for (const f of findings) {
|
|
187
205
|
try {
|
|
188
|
-
upsertFinding(root, f, now);
|
|
206
|
+
const rec = upsertFinding(root, f, now);
|
|
207
|
+
// The Class-A shadow (road-to-org-telemetry Phase 5, step 5.1).
|
|
208
|
+
// Structural fields only — the record type has no member able to
|
|
209
|
+
// hold `f.evidence` or `f.suggested_surface`, which are the
|
|
210
|
+
// Class-B payload and ship only on per-case approval. Inert unless
|
|
211
|
+
// the org pack activated telemetry; a refused record (`null` from
|
|
212
|
+
// the creation cap) emits nothing, because there is no queued
|
|
213
|
+
// defect to shadow.
|
|
214
|
+
if (rec !== null) {
|
|
215
|
+
emitDefectShadow(root, rec, env);
|
|
216
|
+
}
|
|
189
217
|
} catch {
|
|
190
218
|
// an unwritable store must never cost the user their turn
|
|
191
219
|
}
|
|
@@ -208,7 +236,11 @@ export function main(): number {
|
|
|
208
236
|
`${JSON.stringify({
|
|
209
237
|
decision: 'allow',
|
|
210
238
|
reason: `self-repair: ${open.length} open record(s)`,
|
|
211
|
-
context: buildQueueLine(
|
|
239
|
+
context: buildQueueLine(
|
|
240
|
+
open.length,
|
|
241
|
+
open[0]!.defect_class,
|
|
242
|
+
open[0]!.occurrences,
|
|
243
|
+
),
|
|
212
244
|
})}\n`,
|
|
213
245
|
);
|
|
214
246
|
return EXIT_ALLOW;
|
|
@@ -715,6 +715,17 @@ export function foreign_sessions_block(
|
|
|
715
715
|
'',
|
|
716
716
|
`COLLISION: another live session is on branch \`${here}\` in THIS SAME worktree`,
|
|
717
717
|
`(${branch_hit.record.worktree}) — the same files and the same git index.`,
|
|
718
|
+
'What "join anyway" actually costs, because option 1 is chosen routinely and',
|
|
719
|
+
'the price was not in this text until 2026-08-20 (road-to-session-closeout 6.3):',
|
|
720
|
+
' · SHARED INDEX — `git add -A` stages the peer\'s work too. Measured: a peer',
|
|
721
|
+
' session\'s untracked roadmap was swept into an unrelated merge commit and',
|
|
722
|
+
' surfaced three commits later at an estate gate. Use pathspecs, never -A.',
|
|
723
|
+
' · SHARED STASH STACK — `git stash` is repo-wide, so your stash is visible and',
|
|
724
|
+
' poppable by the peer, and `stash@{0}` means a different thing to each of you.',
|
|
725
|
+
' · PRE-PUSH runs over the shared tree — it sees the peer\'s files, not only',
|
|
726
|
+
' yours. `task consistency` is now scoped to the paths it regenerates, so a',
|
|
727
|
+
' peer\'s unrelated edit no longer fails it; anything else in that hook still',
|
|
728
|
+
' reads one tree written by two sessions.',
|
|
718
729
|
'Ask the user ONCE PER SESSION, as numbered options, before writing anything:',
|
|
719
730
|
' 1. Join anyway and coordinate manually (this register is advisory, not a lock)',
|
|
720
731
|
' 2. Spawn a separate worktree for this session',
|
|
@@ -31,7 +31,17 @@ const _HERE = fileURLToPath(import.meta.url);
|
|
|
31
31
|
|
|
32
32
|
// src/scripts/skill_usage_collect.ts → parents[2] of the .py file is repo root.
|
|
33
33
|
export const REPO = path.resolve(path.dirname(_HERE), '..', '..');
|
|
34
|
-
|
|
34
|
+
// `agents/metrics/` was retired by the agents/ taxonomy consolidation (the
|
|
35
|
+
// same finding `skill_overlap.ts` records), so this collector was appending to
|
|
36
|
+
// a directory that does not exist while the real record set sat untouched at
|
|
37
|
+
// `agents/runtime/metrics/skill-usage.jsonl` — last written 2026-05-16. The
|
|
38
|
+
// report script read the same dead path, so the pair agreed with each other
|
|
39
|
+
// and with nothing else. road-to-org-telemetry Phase 0 measured the
|
|
40
|
+
// consequence (spike 3: 0 of 89 invocations detected on the set the collector
|
|
41
|
+
// reads) and named the repair a Phase 4 prerequisite. `runtime/` is the typed,
|
|
42
|
+
// gitignored home for a record set nothing tracks, per the agents/ layout
|
|
43
|
+
// contract.
|
|
44
|
+
const OUT = path.join(REPO, 'agents', 'runtime', 'metrics', 'skill-usage.jsonl');
|
|
35
45
|
|
|
36
46
|
// LISTING_LINE_RE = re.compile(r"^-\s+([a-z0-9][a-z0-9_-]+):\s", re.MULTILINE)
|
|
37
47
|
const LISTING_LINE_RE = /^-\s+([a-z0-9][a-z0-9_-]+):\s/gm;
|