@event4u/agent-config 7.0.0 → 7.0.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/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +33 -517
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +1 -1
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +1 -1
- package/dist/discovery/trust-report.md +1 -1
- package/dist/discovery/workspaces.json +1 -1
- package/dist/install/install.mjs +24 -8
- package/dist/mcp/registry-manifest.json +1 -1
- package/docs/archive/CHANGELOG-7.0.0.md +419 -0
- package/docs/archive/CHANGELOG-pre-7.0.0.md +126 -0
- package/package.json +1 -1
- package/src/scripts/_lib/changelog_eras.ts +58 -0
- package/src/scripts/_lib/installed_lock.ts +47 -12
- package/src/scripts/release.ts +93 -42
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Changelog Archive — pre-7.0.0
|
|
2
|
+
|
|
3
|
+
> Frozen snapshot of `event4u/agent-config` changelog entries
|
|
4
|
+
> released before `7.0.0`, split out of the main
|
|
5
|
+
> [`CHANGELOG.md`](../../CHANGELOG.md) by `scripts/release.py`
|
|
6
|
+
> once the active era's body crossed the drift cap enforced by
|
|
7
|
+
> `tests/test_changelog_eras.py`.
|
|
8
|
+
>
|
|
9
|
+
> **Read-only.** New entries land in `CHANGELOG.md`. Entries
|
|
10
|
+
> here are not amended — git tags remain the canonical source
|
|
11
|
+
> for what shipped.
|
|
12
|
+
>
|
|
13
|
+
> Entry shape follows
|
|
14
|
+
> [`../contracts/CHANGELOG-conventions.md`](../contracts/CHANGELOG-conventions.md).
|
|
15
|
+
|
|
16
|
+
## [6.1.0](https://github.com/event4u-app/agent-config/compare/6.0.0...6.1.0) (2026-06-14)
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
* **rules:** Iron Law — never drop inherited/shared-branch commits without asking ([e03dc18](https://github.com/event4u-app/agent-config/commit/e03dc18300a2ef032d508062be032267a1f1f844))
|
|
21
|
+
* **workspace:** plain-language host-decision explainability + employee-mode gate (6.0.0 P5) ([f485476](https://github.com/event4u-app/agent-config/commit/f485476050d3d7660aa3aaeacc54438e5eee44a9))
|
|
22
|
+
* **governance:** workspace boundary contract + import-edge drift linter (6.0.0 P4) ([943eb29](https://github.com/event4u-app/agent-config/commit/943eb29747eb3dca0988317e2a526cd38d12f06c))
|
|
23
|
+
* **install:** preview-only dry-run for the upgrade-cleanup reaper (6.0.0 P2) ([4caa802](https://github.com/event4u-app/agent-config/commit/4caa802b1fd1bbf1beda71e5ad553000e7b7f2bf))
|
|
24
|
+
* **create-pr:** run the PR-gate archival sweep before opening the PR ([bdd645b](https://github.com/event4u-app/agent-config/commit/bdd645b3bcc7443c00df653d8f53982417d0ca3e))
|
|
25
|
+
* **roadmaps:** deterministic PR-gate archival sweep ([10643ca](https://github.com/event4u-app/agent-config/commit/10643ca9f5ff56ff02f376531e5c8c07998aa08d))
|
|
26
|
+
* **memory:** remove agent-memory Layer 2; file-first memory only ([c8903c6](https://github.com/event4u-app/agent-config/commit/c8903c6f3a5502434b29c1b55535a9ebc3c55ac4))
|
|
27
|
+
* **bench:** v2 pilot run + honest-null report; spawn stratified follow-up (Phase 4-6) ([5b7f7bd](https://github.com/event4u-app/agent-config/commit/5b7f7bd1112462f83ca42ef6509f4871cdba7ebe))
|
|
28
|
+
* **bench:** v2 dual-axis scorer + runner + paired stats (Phase 2-3) ([ae25ee2](https://github.com/event4u-app/agent-config/commit/ae25ee2c7a8b0fe6325a0c886911a8c48c7546d5))
|
|
29
|
+
* **bench:** v2 discipline-axis corpus + fixtures (Phase 0-1) ([1371dd0](https://github.com/event4u-app/agent-config/commit/1371dd05096c38c7f28f0c4a55b1daf2bb230500))
|
|
30
|
+
* **bench:** wrapper-lift A/B benchmark — model-pin, budget-cap, error-aware ([a09238a](https://github.com/event4u-app/agent-config/commit/a09238ad0455baaf6f68016a195ad54725acd3a3))
|
|
31
|
+
* **reasoning:** add model-agnostic Reasoning Discipline Protocol (RDP) ([b4b5bec](https://github.com/event4u-app/agent-config/commit/b4b5bec18f58630add4e7802c9e32b46b88f3084))
|
|
32
|
+
* **security:** Phase 3 consumer audit + runtime injection hook + review skill ([23efe50](https://github.com/event4u-app/agent-config/commit/23efe5001104c1fd7056f7b2216fc4583f7f29f3))
|
|
33
|
+
* **security:** Phase 2 injection-aware authoring rules ([eb41da9](https://github.com/event4u-app/agent-config/commit/eb41da9c7a1e3140d1efad760bd06e0bd53cb513))
|
|
34
|
+
* **security:** Phase 1 self-audit corpus linters + containment convention ([f678aba](https://github.com/event4u-app/agent-config/commit/f678abab7b521f389e16abb837594b3d23a38d5f))
|
|
35
|
+
* **ai-council:** resolve config user-global-first ([9177b52](https://github.com/event4u-app/agent-config/commit/9177b52a99842b3adffc21b325b39610ef520c6d))
|
|
36
|
+
* **ci:** guard against re-introducing external-source references ([88d35d9](https://github.com/event4u-app/agent-config/commit/88d35d913f5afec7db33f5817229b366cac7256f))
|
|
37
|
+
* **doctor:** add read-only stale-orphans health check ([48e6118](https://github.com/event4u-app/agent-config/commit/48e6118eab2e39fbfa1884a9f6defb1c8719a2ba))
|
|
38
|
+
* **packs:** split meta into capability-scoped packs ([b363839](https://github.com/event4u-app/agent-config/commit/b3638393a6c67ecaac41ae19df89b2ed0b03154b))
|
|
39
|
+
* **commands:** add first-class visibility frontmatter field ([db4d88d](https://github.com/event4u-app/agent-config/commit/db4d88dcf41629f27973624d6476f935be32e2c9))
|
|
40
|
+
|
|
41
|
+
### Bug Fixes
|
|
42
|
+
|
|
43
|
+
* **refs:** mark the RDP-contract acceptance criterion as a forward-ref ([c7cee96](https://github.com/event4u-app/agent-config/commit/c7cee966495a5c96932c9f2b71ab72aae517623f))
|
|
44
|
+
* **memory:** mine-session description ≤200 chars + command-count floor ([f368e06](https://github.com/event4u-app/agent-config/commit/f368e0667980e3f3a03233e8152fd23daaa8bc5d))
|
|
45
|
+
* **bench:** lint-bench-ab validates the v2 docs/benchmark.md sections ([41d552b](https://github.com/event4u-app/agent-config/commit/41d552bd3a162577be3a898fca9123cce87b38b9))
|
|
46
|
+
* **server:** mirror reasoning.* in settings schema (template parity + diff) ([5f77256](https://github.com/event4u-app/agent-config/commit/5f77256da1ecbfa03f3aa1261f23ec940991c2bc))
|
|
47
|
+
* **reasoning:** skill-lint senior sections + valid rule tier (2b) ([7f3e278](https://github.com/event4u-app/agent-config/commit/7f3e2789ab483b6938a39aac303f1fbe2f35792e))
|
|
48
|
+
* **security:** refresh threat-model command effective-hash ([5505b57](https://github.com/event4u-app/agent-config/commit/5505b57fa6e4e4bf02e2891f49a30e6dc9128da1))
|
|
49
|
+
* **security:** tighten security-sensitive-stop — clear long_rule lint regression ([d528126](https://github.com/event4u-app/agent-config/commit/d528126120bf51335267bdde66793343ec376c87))
|
|
50
|
+
* **security:** list agent-security-review + security-audit-config in marketplace.json ([f432a62](https://github.com/event4u-app/agent-config/commit/f432a62d42fab5fc6707b166e869ca8cc2d5d866))
|
|
51
|
+
* **security:** CI — portability reword + settings-schema parity for injection_scan ([fa78a58](https://github.com/event4u-app/agent-config/commit/fa78a589101fd41984d85496666f2fd618e49a1f))
|
|
52
|
+
* **cli:** preflight dependency guard with an actionable message ([ce58c76](https://github.com/event4u-app/agent-config/commit/ce58c7683541a3bc22852186a9764be127f87e4b))
|
|
53
|
+
* **repo:** untrack stray node_modules symlink, ignore symlink form ([67cc9e6](https://github.com/event4u-app/agent-config/commit/67cc9e61deb241aa23e9affaa5adc1fd92d99f14))
|
|
54
|
+
* **refs:** exempt gitignored agents/.harvest-local in check_references ([0d0b170](https://github.com/event4u-app/agent-config/commit/0d0b1702c27c06e96d486211f639148f7ed0628e))
|
|
55
|
+
* **refs:** mark gitignored harvest-local ref in security-pillar roadmap ([3abf215](https://github.com/event4u-app/agent-config/commit/3abf215692cf49ac190248c0007668b5a7b1e1f0))
|
|
56
|
+
* **ci:** guard against empty (0-byte) roadmap files ([5115865](https://github.com/event4u-app/agent-config/commit/511586591171735437bba8cdb106094628a3d611))
|
|
57
|
+
* **roadmaps:** restore competitive-borrow v6 work, drop empty reaping stub ([9fceeb7](https://github.com/event4u-app/agent-config/commit/9fceeb7fc9585965f44e25543a9699d0ff8ee519))
|
|
58
|
+
* **ai-council:** align user-global config path with the setup wizard ([54de5a8](https://github.com/event4u-app/agent-config/commit/54de5a853c271311d79b2b436dd3fa58fa25eb69))
|
|
59
|
+
* **rule:** drop non-portable task-invocations from source-confidentiality backstop ([57e6f7f](https://github.com/event4u-app/agent-config/commit/57e6f7fe5199cc5192ead2a1468ad7d04dd5d5bc))
|
|
60
|
+
* **install:** always-run tag sweep so reaping catches pre-inventory orphans ([91e5418](https://github.com/event4u-app/agent-config/commit/91e541852c30899cb84dd2070f705dfe7947d350))
|
|
61
|
+
* **discovery:** register visibility + new capability packs in schema/vocab ([1fcc72b](https://github.com/event4u-app/agent-config/commit/1fcc72b08fbd13f85c01d3df7fbc98790395ac91))
|
|
62
|
+
|
|
63
|
+
### Documentation
|
|
64
|
+
|
|
65
|
+
* **domain-watch:** capture deferred heavyweight tracks in one watch-note (6.0.0 P6) ([e212e1f](https://github.com/event4u-app/agent-config/commit/e212e1fcebed5d61c63d0719deb485787aca6fde))
|
|
66
|
+
* **changelog:** add 6.0.0 release overview + breaking-changes section (6.0.0 P3) ([fdb4b63](https://github.com/event4u-app/agent-config/commit/fdb4b63cd495489341215430ae12a9866cb8503b))
|
|
67
|
+
* fix stale source-of-truth paths and drop above-fold jargon (6.0.0 P1) ([9ee9870](https://github.com/event4u-app/agent-config/commit/9ee98708e1fdcf612848b393aace48b33a548e99))
|
|
68
|
+
* **roadmaps:** add capability-discoverability follow-up from fable-feedback-3 ([a658c2f](https://github.com/event4u-app/agent-config/commit/a658c2f9c338182d1db2db503ab8ce6aa9c1f42f))
|
|
69
|
+
* **model-recommendation:** add orchestrator→subagent model-routing guidance ([669f83d](https://github.com/event4u-app/agent-config/commit/669f83de5b2e6de590d87f7a093eb098bcf8a086))
|
|
70
|
+
* **roadmaps:** add RDP discoverability roadmap ([c65e1b2](https://github.com/event4u-app/agent-config/commit/c65e1b2648af8bfd2a39a6c6dc74124cfc67101b))
|
|
71
|
+
* **roadmaps:** revise discipline-axis pilot for weak-host-first methodology ([9ccb816](https://github.com/event4u-app/agent-config/commit/9ccb816b1fe449cb537567696487c09a4ea2ee8e))
|
|
72
|
+
* **rules:** replace Merge-gated with PR-gate in roadmap-progress-sync ([c140687](https://github.com/event4u-app/agent-config/commit/c1406876e880babd70a178bb958af89f31c49eec))
|
|
73
|
+
* **roadmaps:** memory-layer-cleanup removal + consolidation plans ([254758f](https://github.com/event4u-app/agent-config/commit/254758f1a24d7898b5828a3396d20b7498370d08))
|
|
74
|
+
* **roadmap:** check-refs:skip discipline-axis bench (external repo citations) ([13c5fdb](https://github.com/event4u-app/agent-config/commit/13c5fdb04016c40488140f59688e9db88eee0d9d))
|
|
75
|
+
* **roadmaps:** agent-memory removal + memory-pipeline consolidation plans ([6fbf6a6](https://github.com/event4u-app/agent-config/commit/6fbf6a6d33571839f8c85b276a8728ff62c606c7))
|
|
76
|
+
* **roadmaps:** 3-condition value bench (v1) + discipline-axis bench (v2) ([f5a89c6](https://github.com/event4u-app/agent-config/commit/f5a89c69e60c345dbb655f3b0dab294d2b56669a))
|
|
77
|
+
* **roadmaps:** RDP eval+promotion follow-up; archive frontier-reasoning parent ([417223b](https://github.com/event4u-app/agent-config/commit/417223bce4a4d04404512cfa804ad872dd11324c))
|
|
78
|
+
* **roadmap:** security pillar — supply-chain integrity + injection-aware authoring ([c15ef6a](https://github.com/event4u-app/agent-config/commit/c15ef6adc17226513660b324b7960dc80125bbf3))
|
|
79
|
+
* **roadmap:** fill in road-to-6.0.0-final-readiness ([46ba5a0](https://github.com/event4u-app/agent-config/commit/46ba5a002fb300afbce43e56b92a945bd0957dec))
|
|
80
|
+
* **roadmap:** add image/brand/typography + greenfield-scaffold roadmaps ([f615452](https://github.com/event4u-app/agent-config/commit/f6154528a7b1ba34fb5543c91ac2c905999d2e8c))
|
|
81
|
+
* **ai-council:** repoint config references to the user-global path ([1307f80](https://github.com/event4u-app/agent-config/commit/1307f804b2c1cc4a2b9a3d2ad1b829f2a7108619))
|
|
82
|
+
* **ai-council:** document user-global config location (ADR-093) ([c501e55](https://github.com/event4u-app/agent-config/commit/c501e557fdb94d7214555a3b53042a275b2dc923))
|
|
83
|
+
* **roadmap:** competitive-borrow plan (source-anonymous) ([9e3c692](https://github.com/event4u-app/agent-config/commit/9e3c692745170ad62b0f67d40afa8aad751e34dd))
|
|
84
|
+
* **roadmap:** close metadata-leanness, spawn tier-removal follow-up ([93d5361](https://github.com/event4u-app/agent-config/commit/93d5361d05d5ddef944d4931c6260e69464d8270))
|
|
85
|
+
* **adr:** ADR-092 defer command tier-alias removal (forcing-function) ([71d2630](https://github.com/event4u-app/agent-config/commit/71d26300d14c9b894dfef19ed6a6b3c996f5895f))
|
|
86
|
+
* **roadmap:** metadata & command-surface leanness plan + evidence ([b31d106](https://github.com/event4u-app/agent-config/commit/b31d1061f5816eb3a8aadd4bd154e76ee00d089a))
|
|
87
|
+
* **roadmap:** archive completed reaping-orphans fix plan ([c1ed447](https://github.com/event4u-app/agent-config/commit/c1ed4478f14c634c5fde5dbed224f72ae2c6eedb))
|
|
88
|
+
* record evidence-gated decisions, archive residuals roadmap ([3657e12](https://github.com/event4u-app/agent-config/commit/3657e12fbcacb4740b4d1d84309d7dea28cd3c58))
|
|
89
|
+
|
|
90
|
+
### Refactoring
|
|
91
|
+
|
|
92
|
+
* **ai-council:** relocate config out of the repo to user-global ([17fb14a](https://github.com/event4u-app/agent-config/commit/17fb14a03736cb14f2f56861f194e5bfc00e80b9))
|
|
93
|
+
* **commands:** fold fix:pr-bot/developer-comments into fix:pr-comments ([4c1c1c8](https://github.com/event4u-app/agent-config/commit/4c1c1c8795d422e1ba8d5ae77409f43f3b8fb2e5))
|
|
94
|
+
|
|
95
|
+
### Tests
|
|
96
|
+
|
|
97
|
+
* lower command-surface floor to 148 after fix:pr-* fold ([2b5e9ef](https://github.com/event4u-app/agent-config/commit/2b5e9ef7f6a8160aac6d2d26bb2876d7d8ed1427))
|
|
98
|
+
* **install:** lock the reaping-gap class against regression ([d7ca6d0](https://github.com/event4u-app/agent-config/commit/d7ca6d0f967672d02d0b367fcfa408f6d675a220))
|
|
99
|
+
|
|
100
|
+
### CI
|
|
101
|
+
|
|
102
|
+
* **skill-lint:** also enforce rule tiers + guard the CI wiring ([6cde280](https://github.com/event4u-app/agent-config/commit/6cde2809c5ace248807236dee9634a590955795d))
|
|
103
|
+
* **skill-lint:** run lint-command-tiers on every PR ([2e123c6](https://github.com/event4u-app/agent-config/commit/2e123c696a6bf2047cbc4473a9555c51b8f33da8))
|
|
104
|
+
|
|
105
|
+
### Chores
|
|
106
|
+
|
|
107
|
+
* **roadmaps:** complete + archive road-to-6.0.0-final-readiness (6.0.0) ([652294a](https://github.com/event4u-app/agent-config/commit/652294ad01ad48a2875ebd75953b82d06c350e56))
|
|
108
|
+
* **roadmaps:** archive completed memory-layer-cleanup roadmaps ([9380482](https://github.com/event4u-app/agent-config/commit/9380482cf512c73f0783ff7a2270793d5dca8b95))
|
|
109
|
+
* **memory:** regenerate pack manifest for shortened mine-session description ([14cec0e](https://github.com/event4u-app/agent-config/commit/14cec0ed0c6de254639e3727d7ad1f3a3147902e))
|
|
110
|
+
* **memory:** regenerate projections, catalogs, and dashboard ([78cc1a1](https://github.com/event4u-app/agent-config/commit/78cc1a1180f6eced4c60e0c408da1103d0621ab0))
|
|
111
|
+
* **roadmaps:** regenerate progress dashboard ([d0d2757](https://github.com/event4u-app/agent-config/commit/d0d2757e93026fab6f995732a130f126371e7978))
|
|
112
|
+
* **security:** archive road-to-security-pillar (Phases 1-3 shipped) ([ad5f552](https://github.com/event4u-app/agent-config/commit/ad5f55204bae429b960db40976c3dc40ea759f97))
|
|
113
|
+
* **security:** bump command-count messaging 148→149 (new /security-audit-config) ([5f5b79a](https://github.com/event4u-app/agent-config/commit/5f5b79a1d741b1565cfbc0aaf8c74aa43165fd0b))
|
|
114
|
+
* **security:** regenerate dist, router, counts, pack manifests ([84ff0fc](https://github.com/event4u-app/agent-config/commit/84ff0fcd1216fbbd05a3a340148f681b95c2d4a8))
|
|
115
|
+
* add uncomitted roadmaps ([699c2c5](https://github.com/event4u-app/agent-config/commit/699c2c5e8a70453a46b9c70e68ba621f96a5f64c))
|
|
116
|
+
* **condense:** reconcile stale condensation hashes ([d9ac27e](https://github.com/event4u-app/agent-config/commit/d9ac27e232cc60dba941f75632dde9a5bbd2c4db))
|
|
117
|
+
* add uncomitted roadmaps ([28ff06c](https://github.com/event4u-app/agent-config/commit/28ff06ce3741db46a5d39e1bc0a2a698d3a94c1f))
|
|
118
|
+
* **rules:** track anonymized harvest roadmaps; harden source-confidentiality ([bc77fb9](https://github.com/event4u-app/agent-config/commit/bc77fb93476c8045cd227f94ad09b0f1f3cebbdd))
|
|
119
|
+
* sync stale condensation for work / agents-init / agents-optimize ([0f816ca](https://github.com/event4u-app/agent-config/commit/0f816cae017824af718cd750457bfc1476252927))
|
|
120
|
+
* sync command-count messaging to 148 after fix:pr-* removal ([94097ce](https://github.com/event4u-app/agent-config/commit/94097ce0bee1739d2f54688705b1aaf78a73cee4))
|
|
121
|
+
* sync stale condensation hashes for unchanged command files ([a32da9a](https://github.com/event4u-app/agent-config/commit/a32da9a5c4199d1148549f63bf7c0012496cd2b6))
|
|
122
|
+
* remove external-source references from the tracked tree ([3248611](https://github.com/event4u-app/agent-config/commit/3248611a8ae2e7d0574ba8e121f85077faae9f69))
|
|
123
|
+
* **commands:** backfill visibility + re-tag pack across command sources ([d08f5b6](https://github.com/event4u-app/agent-config/commit/d08f5b6550735db22f4f855f155d2fd91a8dc047))
|
|
124
|
+
* **changelog:** split era 5.9.x → pre-6.0.0 ([c442750](https://github.com/event4u-app/agent-config/commit/c44275053c07352402e162d6accbe67f6d380010))
|
|
125
|
+
|
|
126
|
+
Tests: 6068
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@event4u/agent-config",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.1",
|
|
4
4
|
"description": "Universal AI Agent OS — audited skills, governance rules, commands, and templates for AI coding tools (Claude Code, Cursor, Windsurf, Copilot).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"private": false,
|
|
@@ -126,6 +126,64 @@ export function current_era_body_size(lines: readonly string[] | null = null): n
|
|
|
126
126
|
return next_era_line - current_idx - 1;
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
+
/**
|
|
130
|
+
* Lines in the current era body EXCLUDING the newest (topmost) released
|
|
131
|
+
* version section.
|
|
132
|
+
*
|
|
133
|
+
* The drift cap bounds *accumulated prior* releases in the current era — the
|
|
134
|
+
* mechanism by which "growth forces an era split" (see
|
|
135
|
+
* `docs/contracts/CHANGELOG-conventions.md § Era splits`). The newest released
|
|
136
|
+
* section is exempt: a single release is allowed to be arbitrarily large and
|
|
137
|
+
* instead forces the split on the **next** bump, once it has become a prior
|
|
138
|
+
* entry. Without this exemption a single large catch-up release — e.g. a
|
|
139
|
+
* 376-commit bump whose `## [x.y.z]` section alone exceeds the cap — trips the
|
|
140
|
+
* gate with no era split that could ever bring it under, which is the exact
|
|
141
|
+
* failure this function fixes.
|
|
142
|
+
*
|
|
143
|
+
* Returns the same count as {@link current_era_body_size} when the era holds no
|
|
144
|
+
* released section yet (nothing to exempt).
|
|
145
|
+
*/
|
|
146
|
+
export function current_era_accumulated_body_size(lines: readonly string[] | null = null): number {
|
|
147
|
+
const all = lines ?? read_changelog_lines();
|
|
148
|
+
const spans = era_spans(all);
|
|
149
|
+
const current_idx = current_era_index(spans);
|
|
150
|
+
if (current_idx === null) {
|
|
151
|
+
return 0;
|
|
152
|
+
}
|
|
153
|
+
let next_era_line = all.length;
|
|
154
|
+
for (const span of spans) {
|
|
155
|
+
if (span.line_index > current_idx) {
|
|
156
|
+
next_era_line = span.line_index;
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
const total = next_era_line - current_idx - 1;
|
|
161
|
+
if (total <= 0) {
|
|
162
|
+
return total;
|
|
163
|
+
}
|
|
164
|
+
// Topmost (newest) version heading in the era body.
|
|
165
|
+
let first = -1;
|
|
166
|
+
for (let i = current_idx + 1; i < next_era_line; i++) {
|
|
167
|
+
if (VERSION_HEADING_RE.test(all[i]!)) {
|
|
168
|
+
first = i;
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
if (first === -1) {
|
|
173
|
+
return total; // no released section yet → nothing to exempt
|
|
174
|
+
}
|
|
175
|
+
// The next version heading marks where accumulated prior releases begin.
|
|
176
|
+
let next_ver = next_era_line;
|
|
177
|
+
for (let i = first + 1; i < next_era_line; i++) {
|
|
178
|
+
if (VERSION_HEADING_RE.test(all[i]!)) {
|
|
179
|
+
next_ver = i;
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
const newest_section = next_ver - first;
|
|
184
|
+
return Math.max(0, total - newest_section);
|
|
185
|
+
}
|
|
186
|
+
|
|
129
187
|
/** Parse `M.N.x` into `[M, N]`; return null for archived labels. */
|
|
130
188
|
export function parse_era_label(label: string): [number, number] | null {
|
|
131
189
|
const m = ERA_LABEL_RE.exec(label.trim());
|
|
@@ -429,23 +429,58 @@ function tuple_lt(a: [number, number, number], b: [number, number, number]): boo
|
|
|
429
429
|
return false;
|
|
430
430
|
}
|
|
431
431
|
|
|
432
|
-
/** Read `version` from
|
|
433
|
-
|
|
434
|
-
let root = repo_root ?? null;
|
|
435
|
-
if (root === null) {
|
|
436
|
-
// __file__ = src/scripts/_lib/installed_lock.ts → repo root is three
|
|
437
|
-
// levels up (_lib → scripts → src → root), i.e. parents[3] in Python.
|
|
438
|
-
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
439
|
-
root = path.resolve(here, "..", "..", "..");
|
|
440
|
-
}
|
|
432
|
+
/** Read a string `version` from `<dir>/package.json`, or null if absent/malformed. */
|
|
433
|
+
function _read_package_version(dir: string): string | null {
|
|
441
434
|
try {
|
|
442
|
-
const data = JSON.parse(fs.readFileSync(path.join(
|
|
435
|
+
const data = JSON.parse(fs.readFileSync(path.join(dir, "package.json"), { encoding: "utf-8" }));
|
|
443
436
|
const version = (data as { version?: unknown }).version;
|
|
444
437
|
if (typeof version === "string" && version.trim()) {
|
|
445
438
|
return version.trim();
|
|
446
439
|
}
|
|
447
440
|
} catch {
|
|
448
|
-
// Missing / unreadable / malformed package.json →
|
|
441
|
+
// Missing / unreadable / malformed package.json → null.
|
|
442
|
+
}
|
|
443
|
+
return null;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* Walk upward from `start_dir` to the nearest `package.json` carrying a string
|
|
448
|
+
* `version`. Layout-independent: works in the source tree
|
|
449
|
+
* (`src/scripts/_lib/`), a per-file `dist/`, AND the esbuild single-file bundle
|
|
450
|
+
* (`dist/cli/agent-config.js`) where this module's runtime location differs
|
|
451
|
+
* from its source path. Returns null at the filesystem root.
|
|
452
|
+
*/
|
|
453
|
+
export function _find_package_version_upward(start_dir: string): string | null {
|
|
454
|
+
let dir = start_dir;
|
|
455
|
+
for (;;) {
|
|
456
|
+
const found = _read_package_version(dir);
|
|
457
|
+
if (found !== null) {
|
|
458
|
+
return found;
|
|
459
|
+
}
|
|
460
|
+
const parent = path.dirname(dir);
|
|
461
|
+
if (parent === dir) {
|
|
462
|
+
return null; // reached the filesystem root
|
|
463
|
+
}
|
|
464
|
+
dir = parent;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* Read `version` from the package's own `package.json`.
|
|
470
|
+
*
|
|
471
|
+
* With no `repo_root`, the version is resolved by walking **upward** from this
|
|
472
|
+
* module's runtime directory to the nearest `package.json`. A previous fixed
|
|
473
|
+
* `parents[3]` hop assumed the source layout (`src/scripts/_lib/`); in the
|
|
474
|
+
* shipped esbuild bundle the module runs from `dist/cli/`, so three hops
|
|
475
|
+
* overshot the package root → `package.json` not found → `"0.0.0"` → a
|
|
476
|
+
* spurious "downgrade" refusal on `agent-config global` (lockfile recorded a
|
|
477
|
+
* real version, current package read as `0.0.0`). The upward walk is correct
|
|
478
|
+
* in both layouts.
|
|
479
|
+
*/
|
|
480
|
+
export function current_package_version(repo_root?: string | null): string {
|
|
481
|
+
if (repo_root != null) {
|
|
482
|
+
return _read_package_version(repo_root) ?? "0.0.0";
|
|
449
483
|
}
|
|
450
|
-
|
|
484
|
+
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
485
|
+
return _find_package_version_upward(here) ?? "0.0.0";
|
|
451
486
|
}
|
package/src/scripts/release.ts
CHANGED
|
@@ -94,7 +94,7 @@ import type {
|
|
|
94
94
|
SplitPlan} from './_lib/changelog_eras.js';
|
|
95
95
|
import {
|
|
96
96
|
CURRENT_ERA_BODY_CAP,
|
|
97
|
-
|
|
97
|
+
current_era_accumulated_body_size,
|
|
98
98
|
current_era_insertion_point,
|
|
99
99
|
perform_split,
|
|
100
100
|
plan_split,
|
|
@@ -1014,9 +1014,11 @@ function print_preview(plan: Plan): void {
|
|
|
1014
1014
|
process.stdout.write('\n');
|
|
1015
1015
|
}
|
|
1016
1016
|
|
|
1017
|
-
function confirm(prompt: string): boolean {
|
|
1018
|
-
const ans = _input(`${prompt} [y/N] `)
|
|
1019
|
-
|
|
1017
|
+
function confirm(prompt: string): boolean | null {
|
|
1018
|
+
const ans = _input(`${prompt} [y/N] `);
|
|
1019
|
+
if (ans === null) return null; // no usable controlling terminal
|
|
1020
|
+
const norm = ans.trim().toLowerCase();
|
|
1021
|
+
return norm === 'y' || norm === 'yes';
|
|
1020
1022
|
}
|
|
1021
1023
|
|
|
1022
1024
|
/** Can we prompt at all — is fd 0 a TTY, or is a controlling terminal openable? */
|
|
@@ -1033,35 +1035,42 @@ function _canPrompt(): boolean {
|
|
|
1033
1035
|
}
|
|
1034
1036
|
|
|
1035
1037
|
/**
|
|
1036
|
-
* Mirror of Python `input(prompt)` — write prompt, read one line
|
|
1038
|
+
* Mirror of Python `input(prompt)` — write the prompt, read one line from the
|
|
1039
|
+
* controlling terminal. Returns `null` when no terminal is reachable.
|
|
1037
1040
|
*
|
|
1038
|
-
*
|
|
1039
|
-
*
|
|
1040
|
-
*
|
|
1041
|
-
* `
|
|
1042
|
-
*
|
|
1041
|
+
* The answer is ALWAYS read from a freshly opened, blocking `/dev/tty`
|
|
1042
|
+
* (`openSync(..., 'rs')`), NEVER from fd 0. `task release` / `./scripts-run`
|
|
1043
|
+
* run this under go-task's `interactive: true`, which leaves fd 0 a TTY
|
|
1044
|
+
* (`process.stdin.isTTY === true`) but one Node treats as NON-blocking — so a
|
|
1045
|
+
* bare `readSync(0)` throws `EAGAIN`, the catch swallows it, and the `[y/N]`
|
|
1046
|
+
* prompt "auto-aborts" without ever waiting (the exact failure this fixes;
|
|
1047
|
+
* reproduced with `isTTY === true`). A fresh blocking `/dev/tty` descriptor
|
|
1048
|
+
* blocks for real input regardless of how the script was invoked — the proven
|
|
1049
|
+
* synchronous-prompt pattern.
|
|
1043
1050
|
*/
|
|
1044
|
-
function _input(prompt: string): string {
|
|
1051
|
+
function _input(prompt: string): string | null {
|
|
1045
1052
|
process.stdout.write(prompt);
|
|
1046
|
-
let fd
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
return ''; // no controlling terminal (true non-interactive); guarded by _canPrompt upstream.
|
|
1054
|
-
}
|
|
1053
|
+
let fd: number;
|
|
1054
|
+
try {
|
|
1055
|
+
// 'rs' → O_RDONLY | O_SYNC: a fresh, blocking descriptor on the
|
|
1056
|
+
// controlling terminal, unaffected by Node's non-blocking fd 0.
|
|
1057
|
+
fd = fs.openSync('/dev/tty', 'rs');
|
|
1058
|
+
} catch {
|
|
1059
|
+
return null; // no controlling terminal (true non-interactive)
|
|
1055
1060
|
}
|
|
1056
1061
|
try {
|
|
1057
1062
|
const buf = Buffer.alloc(1);
|
|
1058
1063
|
const chars: number[] = [];
|
|
1059
|
-
|
|
1064
|
+
for (;;) {
|
|
1060
1065
|
let bytesRead: number;
|
|
1061
1066
|
try {
|
|
1062
1067
|
bytesRead = fs.readSync(fd, buf, 0, 1, null);
|
|
1063
|
-
} catch {
|
|
1064
|
-
|
|
1068
|
+
} catch (e) {
|
|
1069
|
+
const code = (e as NodeJS.ErrnoException).code;
|
|
1070
|
+
// A blocking /dev/tty should not yield these, but inherited
|
|
1071
|
+
// descriptor flags can — retry rather than abort the prompt.
|
|
1072
|
+
if (code === 'EAGAIN' || code === 'EINTR') continue;
|
|
1073
|
+
break; // EOF / EIO → EOFError analogue; return what we have.
|
|
1065
1074
|
}
|
|
1066
1075
|
if (bytesRead === 0) break;
|
|
1067
1076
|
const b = buf[0] as number;
|
|
@@ -1070,7 +1079,7 @@ function _input(prompt: string): string {
|
|
|
1070
1079
|
}
|
|
1071
1080
|
return Buffer.from(chars).toString('utf-8');
|
|
1072
1081
|
} finally {
|
|
1073
|
-
|
|
1082
|
+
fs.closeSync(fd);
|
|
1074
1083
|
}
|
|
1075
1084
|
}
|
|
1076
1085
|
|
|
@@ -1090,18 +1099,19 @@ export interface ConfirmVerdict {
|
|
|
1090
1099
|
*/
|
|
1091
1100
|
export function confirmGate(target: string, yes: boolean): ConfirmVerdict {
|
|
1092
1101
|
if (yes) return { proceed: true };
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
}
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1102
|
+
const noTerminal: ConfirmVerdict = {
|
|
1103
|
+
proceed: false,
|
|
1104
|
+
stream: 'stderr',
|
|
1105
|
+
message:
|
|
1106
|
+
'No terminal available for the [y/N] confirmation (non-interactive shell). ' +
|
|
1107
|
+
'Re-run with --yes to confirm, e.g. `task release -- --yes`.',
|
|
1108
|
+
};
|
|
1109
|
+
if (!_canPrompt()) return noTerminal;
|
|
1110
|
+
const answer = confirm(`Proceed with release ${target}?`);
|
|
1111
|
+
// null = the controlling terminal vanished between the probe and the read;
|
|
1112
|
+
// surface the actionable --yes guidance, never a bare silent "aborted.".
|
|
1113
|
+
if (answer === null) return noTerminal;
|
|
1114
|
+
if (!answer) return { proceed: false, stream: 'stdout', message: 'aborted.' };
|
|
1105
1115
|
return { proceed: true };
|
|
1106
1116
|
}
|
|
1107
1117
|
|
|
@@ -1382,6 +1392,7 @@ interface Args {
|
|
|
1382
1392
|
dry_run: boolean;
|
|
1383
1393
|
no_wait: boolean;
|
|
1384
1394
|
resume: boolean;
|
|
1395
|
+
check_confirm: boolean;
|
|
1385
1396
|
}
|
|
1386
1397
|
|
|
1387
1398
|
const PROG = 'release.py';
|
|
@@ -1391,7 +1402,7 @@ const PROG = 'release.py';
|
|
|
1391
1402
|
// not the body prose.
|
|
1392
1403
|
const USAGE =
|
|
1393
1404
|
`usage: ${PROG} [-h] [--as {major,minor,patch}] [--version EXPLICIT] [--yes]\n` +
|
|
1394
|
-
' [--dry-run] [--no-wait] [--resume]\n';
|
|
1405
|
+
' [--dry-run] [--no-wait] [--resume] [--check-confirm]\n';
|
|
1395
1406
|
|
|
1396
1407
|
function _argError(msg: string): never {
|
|
1397
1408
|
process.stderr.write(USAGE);
|
|
@@ -1407,6 +1418,7 @@ function _parse_args(argv: readonly string[]): Args {
|
|
|
1407
1418
|
dry_run: false,
|
|
1408
1419
|
no_wait: false,
|
|
1409
1420
|
resume: false,
|
|
1421
|
+
check_confirm: false,
|
|
1410
1422
|
};
|
|
1411
1423
|
|
|
1412
1424
|
const positionals: string[] = [];
|
|
@@ -1481,6 +1493,13 @@ function _parse_args(argv: readonly string[]): Args {
|
|
|
1481
1493
|
i += 1;
|
|
1482
1494
|
continue;
|
|
1483
1495
|
}
|
|
1496
|
+
if (flag === '--check-confirm') {
|
|
1497
|
+
if (inlineVal !== null)
|
|
1498
|
+
_argError(`argument --check-confirm: ignored explicit argument '${inlineVal}'`);
|
|
1499
|
+
args.check_confirm = true;
|
|
1500
|
+
i += 1;
|
|
1501
|
+
continue;
|
|
1502
|
+
}
|
|
1484
1503
|
if (a.startsWith('-') && a !== '-') {
|
|
1485
1504
|
_argError(`unrecognized arguments: ${a}`);
|
|
1486
1505
|
}
|
|
@@ -1560,6 +1579,32 @@ function _detect_in_flight_target(): string | null {
|
|
|
1560
1579
|
function main(argv: readonly string[] | null = null): number {
|
|
1561
1580
|
const args = _parse_args(argv === null ? process.argv.slice(2) : argv);
|
|
1562
1581
|
|
|
1582
|
+
// Self-test the confirmation prompt without touching git/gh/npm. Run it the
|
|
1583
|
+
// same way a real release is invoked — `task release -- --check-confirm` —
|
|
1584
|
+
// to verify the `[y/N]` prompt can actually read your answer through the
|
|
1585
|
+
// go-task / scripts-run wrapper chain. Nothing is released either way.
|
|
1586
|
+
if (args.check_confirm) {
|
|
1587
|
+
process.stdout.write(
|
|
1588
|
+
'Confirm-gate self-test — answer the [y/N] prompt below.\n' +
|
|
1589
|
+
'Nothing is released; this only checks that the prompt can read your answer.\n',
|
|
1590
|
+
);
|
|
1591
|
+
const verdict = confirmGate('SELF-TEST (no release)', args.yes);
|
|
1592
|
+
if (verdict.proceed) {
|
|
1593
|
+
process.stdout.write(
|
|
1594
|
+
'result: OK — the prompt read your confirmation. ' +
|
|
1595
|
+
'`task release` will work interactively.\n',
|
|
1596
|
+
);
|
|
1597
|
+
return 0;
|
|
1598
|
+
}
|
|
1599
|
+
const sink = verdict.stream === 'stderr' ? process.stderr : process.stdout;
|
|
1600
|
+
if (verdict.message) sink.write(`${verdict.message}\n`);
|
|
1601
|
+
process.stdout.write(
|
|
1602
|
+
`result: the prompt did not read a "y" (stdin.isTTY=${String(process.stdin.isTTY)}). ` +
|
|
1603
|
+
'If you typed y and still see this, paste this whole block back.\n',
|
|
1604
|
+
);
|
|
1605
|
+
return 1;
|
|
1606
|
+
}
|
|
1607
|
+
|
|
1563
1608
|
const current = (
|
|
1564
1609
|
JSON.parse(fs.readFileSync(PACKAGE_JSON, 'utf-8')) as Record<string, unknown>
|
|
1565
1610
|
)['version'] as string;
|
|
@@ -1596,12 +1641,18 @@ function main(argv: readonly string[] | null = null): number {
|
|
|
1596
1641
|
test_trend_line,
|
|
1597
1642
|
});
|
|
1598
1643
|
|
|
1599
|
-
// Era-split planning: only crosses the gate when the current era
|
|
1600
|
-
//
|
|
1601
|
-
//
|
|
1602
|
-
//
|
|
1644
|
+
// Era-split planning: only crosses the gate when the current era's
|
|
1645
|
+
// *accumulated* body (prior releases, excluding the newest section) has
|
|
1646
|
+
// grown past the drift cap AND the release crosses a minor/major boundary.
|
|
1647
|
+
// The newest release is exempt — a single large catch-up release forces
|
|
1648
|
+
// the split on the *next* minor/major once it has become a prior entry,
|
|
1649
|
+
// not on the patch that immediately follows it. This is the same quantity
|
|
1650
|
+
// the drift test enforces (current_era_accumulated_body_size); measuring
|
|
1651
|
+
// the raw total here would re-fire the gate the exemption exists to clear.
|
|
1652
|
+
// Patch overflow that genuinely accumulates is caught by the drift test
|
|
1653
|
+
// (red CI), not by an auto-split into a nonsensical "pre-X.Y.Z" archive.
|
|
1603
1654
|
let split: SplitPlan | null = null;
|
|
1604
|
-
const body_size =
|
|
1655
|
+
const body_size = current_era_accumulated_body_size();
|
|
1605
1656
|
if (body_size > CURRENT_ERA_BODY_CAP) {
|
|
1606
1657
|
const candidate = plan_split(target);
|
|
1607
1658
|
if (candidate === null) {
|