instar 1.3.173 → 1.3.174

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "instar",
3
- "version": "1.3.173",
3
+ "version": "1.3.174",
4
4
  "description": "Coherence infrastructure for self-evolving AI agents — on the Claude Code or Codex subscription you already have.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -165,6 +165,27 @@ try {
165
165
  (srcChanges.length > 5 ? `\n • ...and ${srcChanges.length - 5} more` : '')
166
166
  );
167
167
  }
168
+
169
+ // ── 3b. Release-fragment gate (#23: src change without a release note) ─
170
+ // A shippable src/ change MUST carry a release-note fragment. publish.yml
171
+ // SILENTLY skips the release when there is no upgrades/next/<slug>.md fragment
172
+ // (and no upgrades/NEXT.md) — so the fix merges but never ships, with no
173
+ // signal. Mirror of the src→tests check above. The "chore: release" cut commit
174
+ // touches upgrades/ but not src/, so it never trips this. Bypass genuine WIP
175
+ // with INSTAR_PRE_PUSH_SKIP=1.
176
+ const fragmentChanges = changedFiles.filter(f =>
177
+ f.startsWith('upgrades/next/') || f === 'upgrades/NEXT.md'
178
+ );
179
+ if (srcChanges.length > 0 && fragmentChanges.length === 0) {
180
+ errors.push(
181
+ `${srcChanges.length} source file(s) changed but no release-note fragment was added. ` +
182
+ `Without upgrades/next/<slug>.md (or upgrades/NEXT.md), publish.yml SILENTLY SKIPS the ` +
183
+ `release — your change would merge but never ship. Add a fragment describing the change:\n` +
184
+ srcChanges.slice(0, 5).map(f => ` • ${f}`).join('\n') +
185
+ (srcChanges.length > 5 ? `\n • ...and ${srcChanges.length - 5} more` : '')
186
+ );
187
+ }
188
+
168
189
  // ── 4. Adapter contract test gate ─────────────────────────────────────
169
190
  // If messaging adapter source files changed, require contract test evidence.
170
191
  // This prevents shipping integration code verified only by mocked unit tests.
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "$schema": "./builtin-manifest.schema.json",
3
3
  "schemaVersion": 1,
4
- "generatedAt": "2026-05-31T16:53:49.605Z",
5
- "instarVersion": "1.3.173",
4
+ "generatedAt": "2026-05-31T18:41:05.487Z",
5
+ "instarVersion": "1.3.174",
6
6
  "entryCount": 193,
7
7
  "entries": {
8
8
  "hook:session-start": {
@@ -0,0 +1,36 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: patch -->
5
+
6
+ ## What Changed
7
+
8
+ Closed a silent-release-skip gap in the dev/release tooling. The post-merge
9
+ publish workflow skips publishing when a change carries no release-note fragment
10
+ — which is correct when nothing needs releasing, but meant a real code change
11
+ could merge with no release note and then never ship, with no signal anywhere.
12
+ The pre-push gate now catches this: if source files changed but no release-note
13
+ fragment is included, the push is rejected with a clear message instead of
14
+ sailing through to a silent no-release. It mirrors the existing "you changed code
15
+ but added no tests" check, never trips on the routine release-cut commit, and
16
+ respects the same work-in-progress bypass.
17
+
18
+ ## What to Tell Your User
19
+
20
+ Nothing required — this is invisible developer-tooling robustness. It prevents a
21
+ fix from quietly merging without ever being released.
22
+
23
+ ## Summary of New Capabilities
24
+
25
+ - The pre-push gate now blocks a source change that has no accompanying
26
+ release-note fragment, so fixes can no longer merge and then silently fail to
27
+ publish.
28
+
29
+ ## Evidence
30
+
31
+ - Root cause: publish.yml sets skip when there is no fragment and no NEXT.md, so a
32
+ source change with neither merges but never releases (the lived #23 failure).
33
+ - New guard in the pre-push gate mirrors the existing source-changed-without-tests
34
+ check; never trips on the release-cut commit (touches upgrades, not source).
35
+ - tests/unit/pre-push-gate.test.ts: +1 test; all 14 pass. Lint + type-check clean.
36
+ - Spec: docs/specs/PRE-PUSH-RELEASE-FRAGMENT-GUARD-SPEC.md (+ ELI16 companion).
@@ -0,0 +1,61 @@
1
+ # Side-Effects Review — Pre-push release-fragment guard (#23)
2
+
3
+ **Version / slug:** `pre-push-release-fragment-guard`
4
+ **Date:** 2026-05-31
5
+ **Author:** echo
6
+
7
+ ## Summary of the change
8
+
9
+ `scripts/pre-push-gate.js` gains a check, mirroring the existing src→tests check:
10
+ if `src/**.ts` changed in the branch diff and no `upgrades/next/*.md` fragment
11
+ (or `upgrades/NEXT.md`) is present, it pushes an error → the gate exits non-zero.
12
+ Closes the #23 silent-release-skip class (a shippable src change merging without
13
+ a release note → publish.yml silently skips → fix never ships).
14
+
15
+ **Files changed (source/scripts):**
16
+ - `scripts/pre-push-gate.js` — +1 check (~13 lines) inside the existing git-diff
17
+ `try` block, after the src→tests check.
18
+
19
+ **Files changed (tests):**
20
+ - `tests/unit/pre-push-gate.test.ts` — +1 content-assertion test (matches the
21
+ file's testing approach for the gate's git-dependent checks).
22
+
23
+ ## Blast radius
24
+
25
+ `scripts/pre-push-gate.js` runs only on `git push` (husky pre-push). It gates
26
+ LOCAL pushes; CI remains the authority for tests. The new check adds one more
27
+ reason a push can be rejected: a src change with no release fragment.
28
+
29
+ ## Behavior delta
30
+
31
+ | Scenario | Before | After |
32
+ |---|---|---|
33
+ | src/ changed + a fragment/NEXT.md present | push proceeds | push proceeds (unchanged) |
34
+ | src/ changed + NO fragment | push proceeds → merges → **silent no-release** | push **rejected** with a clear message |
35
+ | `chore: release` cut commit (touches upgrades/, not src/) | proceeds | proceeds (srcChanges=0, check inert) |
36
+ | docs/test-only PR (no src/**.ts) | proceeds | proceeds (srcChanges=0, check inert) |
37
+ | git unavailable (CI / detached HEAD) | git-diff checks skipped | skipped (same `try/catch`) |
38
+
39
+ ## Risks considered
40
+
41
+ - **False-positive blocking a legitimate push?** Only when src/ changed with no
42
+ release note — which is exactly the bug. Genuine WIP bypasses via the existing
43
+ `INSTAR_PRE_PUSH_SKIP=1`. The release-cut commit and docs/test-only PRs don't
44
+ trip it (no src/**.ts).
45
+ - **Severity (error vs warning):** error, because a silent release-skip is a real
46
+ failure (the fix never ships), matching the adapter-contract gate's error
47
+ severity rather than the softer src→tests warning.
48
+ - **No new dependencies, no network, no state.**
49
+
50
+ ## Migration parity
51
+
52
+ None required. `scripts/pre-push-gate.js` is a dev/release tooling script run from
53
+ the repo's husky hook — not an agent-installed file (hook/config/CLAUDE.md
54
+ template/skill). It ships in the repo; no `PostUpdateMigrator` entry needed.
55
+
56
+ ## Test evidence
57
+
58
+ `npx vitest run tests/unit/pre-push-gate.test.ts` → 14 passed (incl. the new
59
+ content-assertion). `npm run lint` + `tsc --noEmit` clean. Dogfood: this PR
60
+ itself carries `upgrades/next/pre-push-release-fragment-guard.md`, so the new
61
+ guard would pass on this very change.