instar 1.3.687 → 1.3.688
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/dist/monitoring/ReleaseReadinessSentinel.d.ts +9 -0
- package/dist/monitoring/ReleaseReadinessSentinel.d.ts.map +1 -1
- package/dist/monitoring/ReleaseReadinessSentinel.js +14 -5
- package/dist/monitoring/ReleaseReadinessSentinel.js.map +1 -1
- package/package.json +1 -1
- package/scripts/check-release-fragment.mjs +152 -0
- package/scripts/lint-no-direct-destructive.js +6 -0
- package/scripts/pre-push-gate.js +11 -4
- package/scripts/release-relevant-paths.mjs +171 -0
- package/scripts/release-skip-annotate.mjs +133 -0
- package/src/data/builtin-manifest.json +2 -2
- package/upgrades/1.3.688.md +61 -0
- package/upgrades/side-effects/release-fragment-gate.md +136 -0
|
@@ -128,6 +128,15 @@ export interface ReleaseReadinessSentinelConfig {
|
|
|
128
128
|
backlogAgeDaysHigh?: number;
|
|
129
129
|
hysteresisHours?: number;
|
|
130
130
|
staleEpisodeTtlDays?: number;
|
|
131
|
+
/**
|
|
132
|
+
* Fast-trigger (RELEASE-FRAGMENT-GATE-SPEC Layer 2, D7): when the block is
|
|
133
|
+
* specifically a missing release-note fragment (guideBlocksPublish) WITH
|
|
134
|
+
* unreleased feature/fix work — the case where publish.yml would SILENTLY
|
|
135
|
+
* SKIP — surface at LOW IMMEDIATELY instead of waiting out the multi-day age
|
|
136
|
+
* floor. This closes the "fresh fragment-less merge sits silent for 2 days"
|
|
137
|
+
* gap that the 2026-06-27 incident exposed. Default on.
|
|
138
|
+
*/
|
|
139
|
+
fastTriggerOnGuideBlock?: boolean;
|
|
131
140
|
}
|
|
132
141
|
export declare class ReleaseReadinessSentinel extends EventEmitter {
|
|
133
142
|
private readonly deps;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReleaseReadinessSentinel.d.ts","sourceRoot":"","sources":["../../src/monitoring/ReleaseReadinessSentinel.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"ReleaseReadinessSentinel.d.ts","sourceRoot":"","sources":["../../src/monitoring/ReleaseReadinessSentinel.ts"],"names":[],"mappings":"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"}
|
|
@@ -39,6 +39,7 @@ const DEFAULTS = {
|
|
|
39
39
|
backlogAgeDaysHigh: 7,
|
|
40
40
|
hysteresisHours: 12,
|
|
41
41
|
staleEpisodeTtlDays: 30,
|
|
42
|
+
fastTriggerOnGuideBlock: true,
|
|
42
43
|
};
|
|
43
44
|
const DAY_MS = 24 * 60 * 60 * 1000;
|
|
44
45
|
const HOUR_MS = 60 * 60 * 1000;
|
|
@@ -150,7 +151,8 @@ export class ReleaseReadinessSentinel extends EventEmitter {
|
|
|
150
151
|
await this.failLoud(state, 'analyzer', new Error('analyze-release returned no report'));
|
|
151
152
|
return;
|
|
152
153
|
}
|
|
153
|
-
const
|
|
154
|
+
const guideBlocks = await this.deps.guideBlocksPublish();
|
|
155
|
+
const blocked = this.isBlocked(report, guideBlocks);
|
|
154
156
|
if (!blocked) {
|
|
155
157
|
// Backlog clear — resolve any open episodes.
|
|
156
158
|
await this.resolveAll(state, 'cleared');
|
|
@@ -167,14 +169,21 @@ export class ReleaseReadinessSentinel extends EventEmitter {
|
|
|
167
169
|
return;
|
|
168
170
|
}
|
|
169
171
|
const ageDays = (this.deps.now() - oldest.dateMs) / DAY_MS;
|
|
170
|
-
const
|
|
172
|
+
const ageBasedPriority = this.priorityForAge(ageDays);
|
|
173
|
+
// Fast-trigger (D7): a missing-fragment block with unreleased feature/fix
|
|
174
|
+
// work is the SILENT-SKIP case — surface at LOW immediately, bypassing the
|
|
175
|
+
// multi-day age floor, instead of letting a fresh fragment-less merge sit
|
|
176
|
+
// silent for days (the 2026-06-27 gap).
|
|
177
|
+
const featureOrFix = report.analysis.commitClassification.features + report.analysis.commitClassification.fixes;
|
|
178
|
+
const fastTriggered = this.cfg.fastTriggerOnGuideBlock && guideBlocks && featureOrFix > 0 && !ageBasedPriority;
|
|
179
|
+
const priority = ageBasedPriority ?? (fastTriggered ? 'LOW' : null);
|
|
171
180
|
let episode = state.episodes.find((e) => e.oldestSha === oldest.sha && !e.resolvedMs);
|
|
172
181
|
if (!episode) {
|
|
173
182
|
episode = { oldestSha: oldest.sha, firstDetectedMs: this.deps.now() };
|
|
174
183
|
state.episodes.push(episode);
|
|
175
184
|
}
|
|
176
185
|
if (!priority) {
|
|
177
|
-
// Below the silent threshold — recorded, no message.
|
|
186
|
+
// Below the silent threshold AND not a fast-trigger case — recorded, no message.
|
|
178
187
|
this.reap(state);
|
|
179
188
|
return;
|
|
180
189
|
}
|
|
@@ -200,8 +209,8 @@ export class ReleaseReadinessSentinel extends EventEmitter {
|
|
|
200
209
|
episode.attentionId = id;
|
|
201
210
|
episode.lastPriority = priority;
|
|
202
211
|
state.lastSignalAt = this.deps.now();
|
|
203
|
-
this.deps.audit({ kind: 'release-readiness', event: 'signal', oldestSha: oldest.sha, priority, ageDays: days, delivered });
|
|
204
|
-
this.emit('signal', { oldestSha: oldest.sha, priority });
|
|
212
|
+
this.deps.audit({ kind: 'release-readiness', event: 'signal', oldestSha: oldest.sha, priority, ageDays: days, delivered, fastTriggered });
|
|
213
|
+
this.emit('signal', { oldestSha: oldest.sha, priority, fastTriggered });
|
|
205
214
|
}
|
|
206
215
|
this.reap(state);
|
|
207
216
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReleaseReadinessSentinel.js","sourceRoot":"","sources":["../../src/monitoring/ReleaseReadinessSentinel.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ReleaseReadinessSentinel.js","sourceRoot":"","sources":["../../src/monitoring/ReleaseReadinessSentinel.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* release-fragment-gate (Layer 1) — the server-side PR-time check that a
|
|
4
|
+
* release-affecting PR carries a release-note fragment.
|
|
5
|
+
*
|
|
6
|
+
* ── Why ───────────────────────────────────────────────────────────────
|
|
7
|
+
* A HARD pre-push gate already requires the fragment, but it runs in husky
|
|
8
|
+
* LOCALLY — the server-side squash/bot/auto-merge path that lands most merges
|
|
9
|
+
* never runs husky, so a fragment-less change reaches main and the publish
|
|
10
|
+
* SILENTLY skips the release (2026-06-27: PRs #1295-#1297 stranded ~7h). This
|
|
11
|
+
* gate moves the SAME requirement to the merge boundary, where it cannot be
|
|
12
|
+
* routed around.
|
|
13
|
+
*
|
|
14
|
+
* ── Signal vs Authority ───────────────────────────────────────────────
|
|
15
|
+
* This is an AUTHORITY (it can block a merge), but its veto rests on an
|
|
16
|
+
* OBJECTIVE BINARY — "a release-note fragment file is present, yes/no" — exactly
|
|
17
|
+
* the shape the existing eli16-pr-gate already establishes. The release-relevant
|
|
18
|
+
* path predicate is a FALLIBLE SIGNAL: a false positive is always escapable by
|
|
19
|
+
* adding a one-line `internal-only` fragment. The block is carried by the
|
|
20
|
+
* presence condition, never the predicate's correctness.
|
|
21
|
+
*
|
|
22
|
+
* ── Security ──────────────────────────────────────────────────────────
|
|
23
|
+
* Runs under `on: pull_request` (NOT pull_request_target), read-only token, no
|
|
24
|
+
* PR-head checkout. Untrusted PR title/body arrive via env (process.env), never
|
|
25
|
+
* shell-interpolated. The bot exemption keys on the AUTHENTICATED actor identity
|
|
26
|
+
* (login + type), never a spoofable title string. FAIL-CLOSED: any internal
|
|
27
|
+
* error reports the check FAILED, never green.
|
|
28
|
+
*
|
|
29
|
+
* Pure `checkReleaseFragment(...)` is exported for unit testing; the CLI wrapper
|
|
30
|
+
* reads env set by the workflow and exits 0 (pass/exempt) or 1 (fail).
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
import { isReleaseRelevant } from './release-relevant-paths.mjs';
|
|
34
|
+
|
|
35
|
+
/** A changed file that is a release-note fragment (the opt-out lane is itself such a file). */
|
|
36
|
+
function isFragmentFile(p) {
|
|
37
|
+
if (typeof p !== 'string') return false;
|
|
38
|
+
const norm = p.trim().replace(/\\/g, '/').replace(/^\.\//, '');
|
|
39
|
+
return /^upgrades\/next\/.+\.md$/.test(norm) || norm === 'upgrades/NEXT.md';
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @param {{
|
|
44
|
+
* files?: Array<{ path: string, status?: string }> | string[],
|
|
45
|
+
* authorLogin?: string|null,
|
|
46
|
+
* authorType?: string|null,
|
|
47
|
+
* title?: string|null,
|
|
48
|
+
* releaseBotLogin?: string|null, // the known release-cut bot login (default github-actions[bot])
|
|
49
|
+
* }} pr
|
|
50
|
+
* @returns {{ ok: boolean, exempt?: string, reason?: string, relevant?: string[] }}
|
|
51
|
+
*/
|
|
52
|
+
export function checkReleaseFragment(pr) {
|
|
53
|
+
const releaseBotLogin = (pr?.releaseBotLogin ?? 'github-actions[bot]');
|
|
54
|
+
|
|
55
|
+
// ── Exemption: ONLY the authenticated release-cut bot identity ──────
|
|
56
|
+
// Keyed on login + type, NEVER a title/commit-message string. A human-authored
|
|
57
|
+
// PR titled "chore: release …" is still gated (the spoof fails by construction).
|
|
58
|
+
const login = String(pr?.authorLogin ?? '');
|
|
59
|
+
const type = String(pr?.authorType ?? '');
|
|
60
|
+
if (type === 'Bot' && login && login === releaseBotLogin) {
|
|
61
|
+
return { ok: true, exempt: 'release-cut-bot' };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Normalize the changed-file list (accept the files API shape OR a bare path list).
|
|
65
|
+
const rawFiles = Array.isArray(pr?.files) ? pr.files : [];
|
|
66
|
+
const paths = rawFiles.map((f) => (typeof f === 'string' ? f : f?.path)).filter((p) => typeof p === 'string');
|
|
67
|
+
|
|
68
|
+
// (a) Any release-relevant changed path?
|
|
69
|
+
const relevant = paths.filter((p) => isReleaseRelevant(p));
|
|
70
|
+
if (relevant.length === 0) {
|
|
71
|
+
return { ok: true, exempt: 'no-release-relevant-paths' };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// (b) A release-note fragment added/modified? (Presence, not content — Layer 1
|
|
75
|
+
// has only the file list. The internal-only opt-out IS such a file, so its
|
|
76
|
+
// presence satisfies this; its legitimacy is verified downstream at
|
|
77
|
+
// assemble-next-md + pre-push-gate §3c.)
|
|
78
|
+
const hasFragment = paths.some(isFragmentFile);
|
|
79
|
+
if (hasFragment) {
|
|
80
|
+
return { ok: true };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return { ok: false, reason: 'release-relevant-no-fragment', relevant };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// ── CLI (used by .github/workflows/release-fragment-gate.yml) ─────────
|
|
87
|
+
const invokedDirectly =
|
|
88
|
+
process.argv[1] && import.meta.url === new URL(`file://${process.argv[1]}`).href;
|
|
89
|
+
|
|
90
|
+
if (invokedDirectly) {
|
|
91
|
+
// FAIL-CLOSED: any throw below exits non-zero (never a silent green).
|
|
92
|
+
try {
|
|
93
|
+
// The workflow provides the changed-file list as JSON in PR_FILES_JSON
|
|
94
|
+
// (array of { path/filename, status }), and PR_AUTHOR_LOGIN / PR_AUTHOR_TYPE
|
|
95
|
+
// / PR_TITLE from the event. WARN_ONLY=1 reports the verdict without failing
|
|
96
|
+
// (soak phase — spec D2/D3).
|
|
97
|
+
let files = [];
|
|
98
|
+
try {
|
|
99
|
+
const parsed = JSON.parse(process.env.PR_FILES_JSON || '[]');
|
|
100
|
+
if (Array.isArray(parsed)) {
|
|
101
|
+
files = parsed.map((f) => ({ path: f.path ?? f.filename, status: f.status }));
|
|
102
|
+
}
|
|
103
|
+
} catch (e) {
|
|
104
|
+
console.error(`release-fragment-gate: could NOT parse PR_FILES_JSON — failing closed. ${e?.message ?? e}`);
|
|
105
|
+
process.exit(1);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const res = checkReleaseFragment({
|
|
109
|
+
files,
|
|
110
|
+
authorLogin: process.env.PR_AUTHOR_LOGIN,
|
|
111
|
+
authorType: process.env.PR_AUTHOR_TYPE,
|
|
112
|
+
title: process.env.PR_TITLE,
|
|
113
|
+
releaseBotLogin: process.env.RELEASE_BOT_LOGIN || undefined,
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
const warnOnly = process.env.WARN_ONLY === '1';
|
|
117
|
+
|
|
118
|
+
if (res.ok) {
|
|
119
|
+
console.log(
|
|
120
|
+
res.exempt
|
|
121
|
+
? `release-fragment-gate: exempt (${res.exempt}).`
|
|
122
|
+
: 'release-fragment-gate: OK — a release-note fragment is present.',
|
|
123
|
+
);
|
|
124
|
+
// Emit a machine-readable verdict line for the rollout log (spec D3).
|
|
125
|
+
console.log(`::notice::release-fragment-gate verdict=PASS exempt=${res.exempt ?? 'none'}`);
|
|
126
|
+
process.exit(0);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const msg =
|
|
130
|
+
`release-fragment-gate: this PR changes release-relevant files but adds NO release-note ` +
|
|
131
|
+
`fragment (upgrades/next/<slug>.md). Without one, the publish pipeline SILENTLY SKIPS the ` +
|
|
132
|
+
`release — your change would merge but never ship (the 2026-06-27 incident).\n` +
|
|
133
|
+
` Release-relevant files:\n` +
|
|
134
|
+
res.relevant.slice(0, 8).map((f) => ` • ${f}`).join('\n') +
|
|
135
|
+
(res.relevant.length > 8 ? `\n • …and ${res.relevant.length - 8} more` : '') +
|
|
136
|
+
`\n Fix: add upgrades/next/<slug>.md describing the change (via /instar-dev). For a genuinely ` +
|
|
137
|
+
`no-user-impact change, add a fragment carrying the standalone <!-- internal-only --> marker.`;
|
|
138
|
+
|
|
139
|
+
if (warnOnly) {
|
|
140
|
+
console.log(`::warning::${msg.replace(/\n/g, ' ')}`);
|
|
141
|
+
console.log(`::notice::release-fragment-gate verdict=FAIL warn-only=1 (not blocking during soak)`);
|
|
142
|
+
process.exit(0); // soak phase: report, do not block
|
|
143
|
+
}
|
|
144
|
+
console.error(msg);
|
|
145
|
+
console.log(`::notice::release-fragment-gate verdict=FAIL blocking=1`);
|
|
146
|
+
process.exit(1);
|
|
147
|
+
} catch (e) {
|
|
148
|
+
// FAIL-CLOSED — an internal error must turn the check RED, never green.
|
|
149
|
+
console.error(`release-fragment-gate: internal error — failing closed. ${e?.stack ?? e}`);
|
|
150
|
+
process.exit(1);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
@@ -134,6 +134,12 @@ const ALLOWLIST = new Set([
|
|
|
134
134
|
// previous release. Build-time only; never executes on an agent's
|
|
135
135
|
// machine. Per INSTAR-JOBS-AS-AGENTMD spec §Drift Classifier.
|
|
136
136
|
'scripts/classify-default-drift.mjs',
|
|
137
|
+
// release-fragment-gate Layer 2 publish-side annotator — runs READ-ONLY git
|
|
138
|
+
// (`describe --tags`, `diff --name-only -z`, `log`, `ls-files`) inside the
|
|
139
|
+
// publish GitHub Action to detect unreleased release-relevant work on a skip.
|
|
140
|
+
// CI-only; never executes on an agent's machine, and TS isn't compiled there
|
|
141
|
+
// so it cannot import the SafeGitExecutor funnel. Per RELEASE-FRAGMENT-GATE-SPEC.
|
|
142
|
+
'scripts/release-skip-annotate.mjs',
|
|
137
143
|
// Tier-3 CI ratchet for the cartographer doc-tree (cartographer-doc-freshness
|
|
138
144
|
// spec #2). A standalone .mjs (parity with docs-coverage.mjs) that runs in CI
|
|
139
145
|
// with NO build step, so it cannot import the TS SafeGitExecutor funnel. All
|
package/scripts/pre-push-gate.js
CHANGED
|
@@ -15,6 +15,7 @@ import path from 'node:path';
|
|
|
15
15
|
import { fileURLToPath } from 'node:url';
|
|
16
16
|
import { validateGuideContent } from './upgrade-guide-validator.mjs';
|
|
17
17
|
import { assembleNextMd, gatherFragmentInputs, hasInternalOnlyMarker } from './assemble-next-md.mjs';
|
|
18
|
+
import { isReleaseRelevant } from './release-relevant-paths.mjs';
|
|
18
19
|
|
|
19
20
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
20
21
|
const ROOT = path.resolve(__dirname, '..');
|
|
@@ -191,13 +192,19 @@ try {
|
|
|
191
192
|
const fragmentChanges = changedFiles.filter(f =>
|
|
192
193
|
f.startsWith('upgrades/next/') || f === 'upgrades/NEXT.md'
|
|
193
194
|
);
|
|
194
|
-
|
|
195
|
+
// Release-relevance is now the SHARED predicate (scripts/release-relevant-paths.mjs),
|
|
196
|
+
// the same one the server-side Layer-1 PR gate uses — so "needs a release note?"
|
|
197
|
+
// has one answer in both places. This BROADENS the old src/**.ts-only check to
|
|
198
|
+
// also catch scripts/, .github/workflows/, package.json, and skill code/templates
|
|
199
|
+
// (all of which ship behavior but previously slipped this local gate).
|
|
200
|
+
const releaseRelevantChanges = changedFiles.filter(isReleaseRelevant);
|
|
201
|
+
if (releaseRelevantChanges.length > 0 && fragmentChanges.length === 0) {
|
|
195
202
|
errors.push(
|
|
196
|
-
`${
|
|
203
|
+
`${releaseRelevantChanges.length} release-relevant file(s) changed but no release-note fragment was added. ` +
|
|
197
204
|
`Without upgrades/next/<slug>.md (or upgrades/NEXT.md), publish.yml SILENTLY SKIPS the ` +
|
|
198
205
|
`release — your change would merge but never ship. Add a fragment describing the change:\n` +
|
|
199
|
-
|
|
200
|
-
(
|
|
206
|
+
releaseRelevantChanges.slice(0, 5).map(f => ` • ${f}`).join('\n') +
|
|
207
|
+
(releaseRelevantChanges.length > 5 ? `\n • ...and ${releaseRelevantChanges.length - 5} more` : '')
|
|
201
208
|
);
|
|
202
209
|
}
|
|
203
210
|
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* release-relevant-paths — the SINGLE SOURCE OF TRUTH for "does this changed
|
|
4
|
+
* file ship behavior that must carry a release-note fragment?"
|
|
5
|
+
*
|
|
6
|
+
* ── Why this exists ───────────────────────────────────────────────────
|
|
7
|
+
* The release-note fragment requirement was enforced by THREE independent
|
|
8
|
+
* predicates that could drift: `pre-push-gate.js §3b` (`src/**.ts` only — too
|
|
9
|
+
* narrow, missed scripts/workflows), and the publish-side skip is path-blind.
|
|
10
|
+
* On 2026-06-27 PRs #1295-#1297 merged with no fragment and the publish ran
|
|
11
|
+
* green and silently skipped (v1.3.685 stuck ~7h). This module is the one
|
|
12
|
+
* predicate the PR-time gate (Layer 1) AND the local pre-push gate share, so
|
|
13
|
+
* "is this release-relevant?" has exactly one answer everywhere.
|
|
14
|
+
*
|
|
15
|
+
* It answers ONE question: "needs a release note?". It is deliberately NOT
|
|
16
|
+
* `instar-dev-precommit.js`'s `inScope()` — that answers a DIFFERENT question
|
|
17
|
+
* ("needs instar-dev review?") and is intentionally narrower; merging them
|
|
18
|
+
* would silently change which changes require review. (See the spec's D6 +
|
|
19
|
+
* the side-effects artifact for the reconciliation.)
|
|
20
|
+
*
|
|
21
|
+
* ── The predicate (spec D6) ───────────────────────────────────────────
|
|
22
|
+
* RELEASE-RELEVANT (positive): src/, scripts/, .husky/, skills/** code +
|
|
23
|
+
* SKILL.md + templates/, package.json, package-lock.json,
|
|
24
|
+
* .github/workflows/**.
|
|
25
|
+
* EXEMPT (never release-relevant, even under a positive root):
|
|
26
|
+
* any *.test.ts, the tests/ tree, the docs/ tree, a bare *.md (notes/readme)
|
|
27
|
+
* that is NOT a SKILL.md or under a skill templates/ dir, the upgrades/ tree
|
|
28
|
+
* (the fragment dir itself), the .instar/ tree (agent-local), and repo
|
|
29
|
+
* dotfiles like .gitignore.
|
|
30
|
+
*
|
|
31
|
+
* Paths are canonicalized (POSIX separators, no leading ./, `..` REJECTED as
|
|
32
|
+
* relevant — the safe direction) and compared case-insensitively on the
|
|
33
|
+
* segment, so `Src/Foo.TS`, `src/../src/x.ts`, and `src/x.ts/` cannot evade.
|
|
34
|
+
*
|
|
35
|
+
* Pure + exported for unit testing; the CLI wrapper classifies a newline/comma
|
|
36
|
+
* list of paths.
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
/** Canonicalize a changed-file path to a comparable POSIX form. Returns null if it escapes the tree. */
|
|
40
|
+
export function canonicalizePath(raw) {
|
|
41
|
+
if (typeof raw !== 'string') return null;
|
|
42
|
+
let p = raw.trim();
|
|
43
|
+
if (!p) return null;
|
|
44
|
+
// Normalize separators + strip a leading ./, collapse duplicate slashes.
|
|
45
|
+
p = p.replace(/\\/g, '/').replace(/\/+/g, '/').replace(/^\.\//, '').replace(/\/+$/, '');
|
|
46
|
+
if (!p) return null;
|
|
47
|
+
// Reject any traversal segment — a `..` path is treated as release-relevant
|
|
48
|
+
// by the caller (fail toward "in scope"), never silently exempt.
|
|
49
|
+
const segments = p.split('/');
|
|
50
|
+
if (segments.some((s) => s === '..')) return { escaped: true, path: p };
|
|
51
|
+
return { escaped: false, path: p };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Lowercase form for case-insensitive matching (covers macOS/Windows case-fold FS). */
|
|
55
|
+
function lc(p) {
|
|
56
|
+
return p.toLowerCase();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Is this changed file release-relevant (needs a release-note fragment)?
|
|
61
|
+
* @param {string} rawPath a repo-relative changed-file path
|
|
62
|
+
* @returns {boolean}
|
|
63
|
+
*/
|
|
64
|
+
export function isReleaseRelevant(rawPath) {
|
|
65
|
+
const c = canonicalizePath(rawPath);
|
|
66
|
+
if (c === null) return false;
|
|
67
|
+
// A traversal path is ambiguous → bias toward release-relevant (the safe
|
|
68
|
+
// direction: a false "needs a note" is escapable with a one-line fragment; a
|
|
69
|
+
// false exempt silently re-opens the 2026-06-27 silent-skip).
|
|
70
|
+
if (c.escaped) return true;
|
|
71
|
+
const p = lc(c.path);
|
|
72
|
+
|
|
73
|
+
// ── EXEMPT (checked first — exemptions override positive roots) ──────
|
|
74
|
+
// Test files anywhere.
|
|
75
|
+
if (p.endsWith('.test.ts') || p.endsWith('.test.js') || p.endsWith('.test.mjs')) return false;
|
|
76
|
+
if (p === 'tests' || p.startsWith('tests/')) return false;
|
|
77
|
+
// Docs + the release-notes machinery itself.
|
|
78
|
+
if (p === 'docs' || p.startsWith('docs/')) return false;
|
|
79
|
+
if (p === 'upgrades' || p.startsWith('upgrades/')) return false;
|
|
80
|
+
// Agent-local + repo dotfiles that ship no runtime behavior.
|
|
81
|
+
if (p.startsWith('.instar/')) return false;
|
|
82
|
+
if (p.startsWith('.github/') && !p.startsWith('.github/workflows/')) return false; // ISSUE_TEMPLATE etc.
|
|
83
|
+
|
|
84
|
+
// ── POSITIVE (release-relevant) ─────────────────────────────────────
|
|
85
|
+
if (p === 'package.json' || p === 'package-lock.json') return true;
|
|
86
|
+
if (p.startsWith('.github/workflows/')) return true;
|
|
87
|
+
if (p.startsWith('src/')) return true;
|
|
88
|
+
if (p.startsWith('scripts/')) return true;
|
|
89
|
+
if (p.startsWith('.husky/')) return true;
|
|
90
|
+
// Built-in skills under skills/ ship behavior.
|
|
91
|
+
if (p.startsWith('skills/')) return isSkillPathRelevant(p);
|
|
92
|
+
// SHIPPED .claude paths (package.json `files`): .claude/hooks/** and the
|
|
93
|
+
// built-in .claude/skills/<name>/ dirs are hand-maintained behavior that
|
|
94
|
+
// reaches the fleet via npm — NOT exempt (the second-pass-review fix). Other
|
|
95
|
+
// .claude/** is agent-local and not shipped → exempt.
|
|
96
|
+
if (p.startsWith('.claude/hooks/')) return true;
|
|
97
|
+
if (p.startsWith('.claude/skills/') && SHIPPED_CLAUDE_SKILLS.some((n) => p.startsWith(`.claude/skills/${n}/`))) {
|
|
98
|
+
return isSkillPathRelevant(p);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// ── Everything else: a bare *.md, assets, examples, site, etc. → exempt.
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** Built-in .claude/skills/<name> dirs shipped via package.json `files`. */
|
|
106
|
+
const SHIPPED_CLAUDE_SKILLS = ['setup-wizard', 'secret-setup', 'autonomous', 'build'];
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Within a skill dir, classify a path. FAIL TOWARD RELEVANT: a SKILL.md, a
|
|
110
|
+
* templates/ file, or ANY code/data file is relevant; only a bare doc *.md that
|
|
111
|
+
* is NOT a SKILL.md and NOT under templates/ is exempt. (Broadened from a fixed
|
|
112
|
+
* extension allowlist so .cjs/.py/.json and future code types are not silently
|
|
113
|
+
* exempted — the second-pass-review fix.)
|
|
114
|
+
*/
|
|
115
|
+
function isSkillPathRelevant(p) {
|
|
116
|
+
if (p.endsWith('/skill.md')) return true;
|
|
117
|
+
if (p.includes('/templates/')) return true;
|
|
118
|
+
if (p.endsWith('.md')) return false; // a non-SKILL.md skill doc
|
|
119
|
+
return true; // any other file under a skill ships behavior/data
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Classify a list of changed-file paths.
|
|
124
|
+
* @param {string[]} paths
|
|
125
|
+
* @returns {{ relevant: string[], exempt: string[] }}
|
|
126
|
+
*/
|
|
127
|
+
export function classifyPaths(paths) {
|
|
128
|
+
const relevant = [];
|
|
129
|
+
const exempt = [];
|
|
130
|
+
for (const raw of paths) {
|
|
131
|
+
const c = canonicalizePath(raw);
|
|
132
|
+
const display = c && !c.escaped ? c.path : (typeof raw === 'string' ? raw.trim() : String(raw));
|
|
133
|
+
if (isReleaseRelevant(raw)) relevant.push(display);
|
|
134
|
+
else if (display) exempt.push(display);
|
|
135
|
+
}
|
|
136
|
+
return { relevant, exempt };
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* The current top-level shipped/runtime roots, derived from package.json `files`.
|
|
141
|
+
* Used by the anti-drift guard test: a NEW top-level root the predicate does not
|
|
142
|
+
* explicitly classify must fail the test, so a future release-bearing directory
|
|
143
|
+
* cannot silently fall through as a false-negative (spec D6 anti-drift rule).
|
|
144
|
+
* @param {string[]} filesWhitelist package.json `files`
|
|
145
|
+
* @returns {string[]} distinct top-level segments
|
|
146
|
+
*/
|
|
147
|
+
export function shippedTopLevelRoots(filesWhitelist) {
|
|
148
|
+
const roots = new Set();
|
|
149
|
+
for (const entry of filesWhitelist || []) {
|
|
150
|
+
const c = canonicalizePath(entry);
|
|
151
|
+
if (!c || c.escaped) continue;
|
|
152
|
+
const top = c.path.split('/')[0];
|
|
153
|
+
if (top) roots.add(top);
|
|
154
|
+
}
|
|
155
|
+
return [...roots].sort();
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// ── CLI: classify a newline/comma-separated list of paths from argv/stdin ──
|
|
159
|
+
const invokedDirectly =
|
|
160
|
+
process.argv[1] && import.meta.url === new URL(`file://${process.argv[1]}`).href;
|
|
161
|
+
|
|
162
|
+
if (invokedDirectly) {
|
|
163
|
+
const arg = process.argv.slice(2).join(' ').trim();
|
|
164
|
+
let input = arg;
|
|
165
|
+
if (!input) {
|
|
166
|
+
try { input = require('node:fs').readFileSync(0, 'utf8'); } catch { input = ''; }
|
|
167
|
+
}
|
|
168
|
+
const paths = input.split(/[\n,]/).map((s) => s.trim()).filter(Boolean);
|
|
169
|
+
const { relevant, exempt } = classifyPaths(paths);
|
|
170
|
+
process.stdout.write(JSON.stringify({ relevant, exempt, releaseRelevant: relevant.length > 0 }, null, 2) + '\n');
|
|
171
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* release-skip-annotate (Layer 2, publish-side) — when the publish pipeline is
|
|
4
|
+
* about to SKIP a release (no fragment → no version), check whether
|
|
5
|
+
* release-relevant work has merged since the last published tag, and if so emit
|
|
6
|
+
* a LOUD, count-capped annotation + step summary instead of a silent green run.
|
|
7
|
+
*
|
|
8
|
+
* Spec: docs/specs/RELEASE-FRAGMENT-GATE-SPEC.md (Layer 2, D1/D7/D11).
|
|
9
|
+
*
|
|
10
|
+
* It is a SIGNAL: it NEVER fails the run (always exits 0) and NEVER claims to
|
|
11
|
+
* raise an Attention item (a CI runner cannot reach the agent's Attention store —
|
|
12
|
+
* the durable surface is the agent-side ReleaseReadinessSentinel). Commit data is
|
|
13
|
+
* read NUL-delimited via execFile argv arrays — never a shell string — and never
|
|
14
|
+
* echoed raw through `::`-prefixed workflow commands beyond the bounded message.
|
|
15
|
+
*
|
|
16
|
+
* Boundary (D11): the authoritative window start is the most recent annotated
|
|
17
|
+
* `vX.Y.Z` tag (written only by the release bot, so it is NOT PR-mutable). A
|
|
18
|
+
* missing/unparseable boundary surfaces ALL reachable commits with an eval-note —
|
|
19
|
+
* never a silent empty range.
|
|
20
|
+
*
|
|
21
|
+
* Pure `classifyRange({ files })` is exported for testing; the CLI does the git I/O.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import { execFileSync } from 'node:child_process';
|
|
25
|
+
import fs from 'node:fs';
|
|
26
|
+
import { isReleaseRelevant } from './release-relevant-paths.mjs';
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Given a list of changed file paths in the unreleased window, return the
|
|
30
|
+
* release-relevant subset.
|
|
31
|
+
* @param {{ files: string[] }} input
|
|
32
|
+
* @returns {{ relevant: string[] }}
|
|
33
|
+
*/
|
|
34
|
+
export function classifyRange({ files }) {
|
|
35
|
+
const relevant = (files || []).filter((f) => isReleaseRelevant(f));
|
|
36
|
+
return { relevant };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function git(args) {
|
|
40
|
+
// argv array — never a shell string. NUL-delimited callers split on \0.
|
|
41
|
+
return execFileSync('git', args, { encoding: 'utf8', maxBuffer: 64 * 1024 * 1024 });
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Most recent annotated vX.Y.Z tag reachable from HEAD, or null. */
|
|
45
|
+
function lastReleaseTag() {
|
|
46
|
+
try {
|
|
47
|
+
const out = git(['describe', '--tags', '--match', 'v[0-9]*', '--abbrev=0']).trim();
|
|
48
|
+
return out || null;
|
|
49
|
+
} catch {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Changed files in <range> as an array (NUL-delimited, opaque). */
|
|
55
|
+
function changedFilesInRange(range) {
|
|
56
|
+
// --name-only -z gives NUL-delimited filenames; we never shell-interpolate them.
|
|
57
|
+
const raw = git(['diff', '--name-only', '-z', range]);
|
|
58
|
+
return raw.split('\0').map((s) => s.trim()).filter(Boolean);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Distinct commit subjects in <range> (count-capped, for the summary only). */
|
|
62
|
+
function commitSubjects(range, cap) {
|
|
63
|
+
try {
|
|
64
|
+
const raw = git(['log', '--no-merges', '--format=%s%x00', range]);
|
|
65
|
+
return raw.split('\0').map((s) => s.trim()).filter(Boolean).slice(0, cap);
|
|
66
|
+
} catch {
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const invokedDirectly =
|
|
72
|
+
process.argv[1] && import.meta.url === new URL(`file://${process.argv[1]}`).href;
|
|
73
|
+
|
|
74
|
+
if (invokedDirectly) {
|
|
75
|
+
const SUMMARY_CAP = 20;
|
|
76
|
+
const emit = (line) => process.stdout.write(line + '\n');
|
|
77
|
+
const summaryFile = process.env.GITHUB_STEP_SUMMARY;
|
|
78
|
+
const writeSummary = (text) => {
|
|
79
|
+
if (summaryFile) {
|
|
80
|
+
try { fs.appendFileSync(summaryFile, text + '\n'); } catch { /* best effort */ }
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
// NEVER throw out of here — Layer 2 is signal-only; always exit 0.
|
|
85
|
+
try {
|
|
86
|
+
const tag = lastReleaseTag();
|
|
87
|
+
const range = tag ? `${tag}..HEAD` : null;
|
|
88
|
+
let files;
|
|
89
|
+
let boundaryNote = '';
|
|
90
|
+
if (range) {
|
|
91
|
+
files = changedFilesInRange(range);
|
|
92
|
+
} else {
|
|
93
|
+
// Missing boundary (e.g. first publish before any vX.Y.Z tag) — surface
|
|
94
|
+
// ALL reachable commits with an eval-note, never a silent empty range.
|
|
95
|
+
boundaryNote = ' (no release tag found — surfacing all reachable history)';
|
|
96
|
+
files = (() => { try { return git(['ls-files']).split('\n').map((s) => s.trim()).filter(Boolean); } catch { return []; } })();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const { relevant } = classifyRange({ files });
|
|
100
|
+
if (relevant.length === 0) {
|
|
101
|
+
emit(`::notice::release-skip-annotate: skip is clean — no release-relevant changes since ${tag ?? '(no tag)'}.`);
|
|
102
|
+
process.exit(0);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const subjects = range ? commitSubjects(range, SUMMARY_CAP) : [];
|
|
106
|
+
const capped = relevant.slice(0, SUMMARY_CAP);
|
|
107
|
+
const oneLine =
|
|
108
|
+
`release SKIPPED but ${relevant.length} release-relevant file(s) merged since ${tag ?? 'the start'}${boundaryNote} ` +
|
|
109
|
+
`with NO release-note fragment — these changes are NOT being shipped. Add upgrades/next/<slug>.md and re-publish.`;
|
|
110
|
+
emit(`::warning::${oneLine}`);
|
|
111
|
+
|
|
112
|
+
const summary =
|
|
113
|
+
`## ⚠ Release skipped with unreleased release-relevant work\n\n` +
|
|
114
|
+
`The publish run is about to skip (no release-note fragment), but the following ` +
|
|
115
|
+
`release-relevant files merged since \`${tag ?? '(no tag)'}\`${boundaryNote} and will NOT ship until a ` +
|
|
116
|
+
`fragment is added:\n\n` +
|
|
117
|
+
capped.map((f) => `- \`${f}\``).join('\n') +
|
|
118
|
+
(relevant.length > SUMMARY_CAP ? `\n- …and ${relevant.length - SUMMARY_CAP} more` : '') +
|
|
119
|
+
(subjects.length
|
|
120
|
+
? `\n\nUnreleased commit subjects:\n\n` + subjects.map((s) => `- ${s.replace(/`/g, "'")}`).join('\n')
|
|
121
|
+
: '') +
|
|
122
|
+
`\n\n**Fix:** add \`upgrades/next/<slug>.md\` describing the change (via /instar-dev) and re-publish. ` +
|
|
123
|
+
`The durable, ack-able signal is raised by the agent-side ReleaseReadinessSentinel; this annotation is a ` +
|
|
124
|
+
`best-effort CI surface.\n`;
|
|
125
|
+
writeSummary(summary);
|
|
126
|
+
emit(`::notice::release-skip-annotate verdict=UNRELEASED-WORK count=${relevant.length}`);
|
|
127
|
+
process.exit(0);
|
|
128
|
+
} catch (e) {
|
|
129
|
+
// Signal-only: an internal error must NOT fail the publish run.
|
|
130
|
+
emit(`::warning::release-skip-annotate: internal error (non-fatal, release-skip detection only): ${String(e?.message ?? e)}`);
|
|
131
|
+
process.exit(0);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "./builtin-manifest.schema.json",
|
|
3
3
|
"schemaVersion": 1,
|
|
4
|
-
"generatedAt": "2026-06-
|
|
5
|
-
"instarVersion": "1.3.
|
|
4
|
+
"generatedAt": "2026-06-27T21:14:22.583Z",
|
|
5
|
+
"instarVersion": "1.3.688",
|
|
6
6
|
"entryCount": 202,
|
|
7
7
|
"entries": {
|
|
8
8
|
"hook:session-start": {
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- assembled-by: assemble-next-md -->
|
|
4
|
+
<!-- bump: patch -->
|
|
5
|
+
|
|
6
|
+
## What Changed
|
|
7
|
+
|
|
8
|
+
Added the **release-fragment-gate** so a release-affecting PR can no longer merge and
|
|
9
|
+
then SILENTLY skip the release (the 2026-06-27 incident: PRs #1295-#1297 merged with
|
|
10
|
+
no `upgrades/next/` fragment, the publish ran green and cut no version, fixes stranded
|
|
11
|
+
~7h).
|
|
12
|
+
|
|
13
|
+
The fragment requirement already existed as a HARD local pre-push gate
|
|
14
|
+
(`pre-push-gate.js §3b`) — but husky runs only on a local `git push`, so the
|
|
15
|
+
server-side squash/bot/auto-merge path bypassed it. This change moves the same
|
|
16
|
+
requirement to the merge boundary, server-side, where it can't be routed around:
|
|
17
|
+
|
|
18
|
+
- **Layer 1 — `release-fragment-gate` CI check** (`.github/workflows/release-fragment-gate.yml`
|
|
19
|
+
+ `scripts/check-release-fragment.mjs`): on every PR to `main`, a release-relevant
|
|
20
|
+
change with no fragment is flagged. Ships **warn-only** (reports the verdict, never
|
|
21
|
+
blocks) until the spec's D3 criterion is met and it's registered as a required check.
|
|
22
|
+
Security-hardened: `on: pull_request` (never `pull_request_target`), read-only token,
|
|
23
|
+
the gate code loads from the BASE ref (never PR-head), and the bot exemption keys on
|
|
24
|
+
authenticated identity, not a spoofable title. Fail-closed.
|
|
25
|
+
- **Shared predicate** (`scripts/release-relevant-paths.mjs`): one "is this
|
|
26
|
+
release-relevant?" answer, consumed by both the PR gate and the local pre-push gate
|
|
27
|
+
(`§3b` is broadened from `src/**.ts` to also catch `scripts/`, `.github/workflows/`,
|
|
28
|
+
`package.json`, skill code, and shipped `.claude/hooks` + `.claude/skills`).
|
|
29
|
+
- **Layer 2 — loud-skip backstop**: the publish pipeline now emits a loud warning +
|
|
30
|
+
step summary when it would skip with unreleased release-relevant work
|
|
31
|
+
(`scripts/release-skip-annotate.mjs`, signal-only, never fails the run), and the
|
|
32
|
+
`ReleaseReadinessSentinel` gains a **fast-trigger** so a missing-fragment merge
|
|
33
|
+
surfaces immediately instead of waiting out the multi-day age floor.
|
|
34
|
+
|
|
35
|
+
## What to Tell Your User
|
|
36
|
+
|
|
37
|
+
If a release ever stops cutting versions, the cause is almost always a merged change
|
|
38
|
+
with no "what changed" note — and now you'll be told loudly instead of finding a
|
|
39
|
+
green-but-empty release run hours later. Maintainer agents get an immediate heads-up
|
|
40
|
+
when finished work is sitting unreleased for that reason. Nothing changes for everyday
|
|
41
|
+
users; this is release-pipeline safety for the people who ship instar.
|
|
42
|
+
|
|
43
|
+
## Summary of New Capabilities
|
|
44
|
+
|
|
45
|
+
- A server-side PR check that catches a release-affecting change shipped without a
|
|
46
|
+
release note, before it merges (starts in warn-only mode).
|
|
47
|
+
- One shared rule for "does this change need a release note?", used by both the
|
|
48
|
+
server check and the local pre-push check.
|
|
49
|
+
- A loud alarm (instead of a silent green run) when the publish pipeline skips a
|
|
50
|
+
release that still has unreleased work, plus an immediate maintainer heads-up.
|
|
51
|
+
|
|
52
|
+
## Evidence
|
|
53
|
+
|
|
54
|
+
57 new unit tests (the shared predicate incl. adversarial path-evasion + an anti-drift
|
|
55
|
+
ownership guard, the Layer-1 decision table incl. the bot-spoof evasion case, and the
|
|
56
|
+
Layer-2 classifier) + the extended ReleaseReadinessSentinel suite (fast-trigger fires
|
|
57
|
+
for the missing-fragment case, does NOT fire for a coverage-gap block, honors its
|
|
58
|
+
off-switch). tsc clean. Driven by the converged + approved
|
|
59
|
+
RELEASE-FRAGMENT-GATE-SPEC (3-round spec-converge, 6 internal + codex/gemini external
|
|
60
|
+
reviewers) and an independent second-pass review that caught + fixed a `.claude`
|
|
61
|
+
shipped-path exemption hole before commit.
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# Side-Effects Review — release-fragment-gate
|
|
2
|
+
|
|
3
|
+
Spec: `docs/specs/RELEASE-FRAGMENT-GATE-SPEC.md` (converged + approved).
|
|
4
|
+
Change: a server-side PR-time CI gate + a shared release-relevant predicate + a
|
|
5
|
+
publish-side loud-skip annotation + a ReleaseReadinessSentinel fast-trigger, so a
|
|
6
|
+
release-affecting PR can no longer merge and then silently skip the release.
|
|
7
|
+
|
|
8
|
+
## 1. Over-block — what legitimate inputs does this reject that it shouldn't?
|
|
9
|
+
|
|
10
|
+
- **Layer 1 (PR gate):** a release-relevant PR with no fragment is FAILED. False
|
|
11
|
+
positives = a `src/`/`scripts/` change with genuinely no user impact (refactor,
|
|
12
|
+
logging). Mitigation: the one-line `internal-only` fragment opt-out (diff-verified,
|
|
13
|
+
auditable) clears it. AND the gate **ships warn-only** — it cannot block anything
|
|
14
|
+
until the D3 criterion is met and it is manually registered as required. So
|
|
15
|
+
over-block has zero blast radius at ship time.
|
|
16
|
+
- **Predicate:** biases toward "relevant" on a `..` path (safe direction) — a
|
|
17
|
+
theoretical over-block, but such paths don't occur in normal PRs.
|
|
18
|
+
|
|
19
|
+
## 2. Under-block — what failure modes does this still miss?
|
|
20
|
+
|
|
21
|
+
- Layer 1 checks fragment **presence, not content** (it has only the file list; reading
|
|
22
|
+
content would require executing PR-head code — the security vector we explicitly
|
|
23
|
+
avoid). A junk/empty fragment passes Layer 1 — but does NOT re-open the silent skip:
|
|
24
|
+
`assemble-next-md` THROWS on a content-less fragment (a loud RED publish), and
|
|
25
|
+
`pre-push-gate §3c` diff-verifies the internal-only legitimacy. Worst case = a loud
|
|
26
|
+
downstream failure, never a silent green.
|
|
27
|
+
- A direct push to `main` that bypasses PRs entirely (admin/ruleset escape) skips
|
|
28
|
+
Layer 1 — caught by Layer 2 (the Sentinel poller reads `main` independent of CI).
|
|
29
|
+
- `[skip ci]` on a release-relevant push disables the publish job (incl. the Layer-2
|
|
30
|
+
annotation) — again caught by the agent-side Sentinel poller, not CI.
|
|
31
|
+
|
|
32
|
+
## 3. Level-of-abstraction fit
|
|
33
|
+
|
|
34
|
+
Correct layer. The fragment requirement already existed at the **local** (husky)
|
|
35
|
+
layer; this moves the SAME requirement to the **server/merge-boundary** layer where
|
|
36
|
+
it can't be bypassed, and the durable backstop sits in the **agent-side Sentinel**
|
|
37
|
+
that already owns "unreleased work is piling up." No new parallel watcher — the
|
|
38
|
+
Sentinel is extended (fast-trigger), and the existing eli16-pr-gate establishes the
|
|
39
|
+
blocking-presence-check precedent the Layer-1 gate mirrors.
|
|
40
|
+
|
|
41
|
+
## 4. Signal vs authority compliance (docs/signal-vs-authority.md)
|
|
42
|
+
|
|
43
|
+
Declared explicitly in the spec's `## Signal vs. Authority` section.
|
|
44
|
+
- **Layer 1 = AUTHORITY** but its veto is an OBJECTIVE BINARY ("a fragment file is
|
|
45
|
+
present, yes/no") — the same shape as eli16-pr-gate, NOT a brittle judgment wearing
|
|
46
|
+
blocking authority. The fallible `release-relevant` path predicate is a SIGNAL whose
|
|
47
|
+
false-positives are always escapable via the one-line opt-out — the escape hatch, not
|
|
48
|
+
the predicate's correctness, carries the authority.
|
|
49
|
+
- **Layer 2 = SIGNAL** — the publish annotation never fails the run; the Sentinel
|
|
50
|
+
surfaces an Attention item, never blocks. Compliant.
|
|
51
|
+
|
|
52
|
+
## 5. Interactions — shadowing / double-fire / races
|
|
53
|
+
|
|
54
|
+
- `pre-push-gate §3b` now consumes the shared predicate (BROADENED from `src/**.ts`).
|
|
55
|
+
It is the LOCAL gate; Layer 1 is the SERVER gate. They check the same thing at two
|
|
56
|
+
layers (defense in depth) — intentional, not a double-fire (different surfaces; a
|
|
57
|
+
local push that passes still gets the server check on the PR).
|
|
58
|
+
- `inScope()` (instar-dev review-scope) is deliberately NOT merged into the shared
|
|
59
|
+
predicate — it answers a DIFFERENT question ("needs instar-dev review?") and is
|
|
60
|
+
narrower. Merging would silently change which changes require review. Documented.
|
|
61
|
+
- The Sentinel fast-trigger only adds a NEW path (fires LOW when it previously stayed
|
|
62
|
+
silent for the missing-fragment case); it does not change the age-based escalation,
|
|
63
|
+
dedup, hysteresis, or resolve logic. The existing "stays silent below threshold"
|
|
64
|
+
test was updated to isolate the age semantic (fast-trigger off) — no behavior was
|
|
65
|
+
weakened, a gap was closed.
|
|
66
|
+
|
|
67
|
+
## 6. External surfaces
|
|
68
|
+
|
|
69
|
+
- A NEW required-eligible CI check appears on instar-repo PRs (warn-only at first).
|
|
70
|
+
- The publish run gains a `::warning::` + step-summary on a fragment-less skip.
|
|
71
|
+
- The Sentinel may post an Attention item sooner (LOW, immediately) for the
|
|
72
|
+
missing-fragment case. Same surface (Attention queue), earlier timing.
|
|
73
|
+
- No change visible to end-user agents (this is instar-repo dev infrastructure;
|
|
74
|
+
`.github/` does not ship to the fleet; `scripts/` ships but is CI/gate-only).
|
|
75
|
+
|
|
76
|
+
## 7. Multi-machine posture (Cross-Machine Coherence)
|
|
77
|
+
|
|
78
|
+
- **Layer 1 + Layer 2 publish annotation:** run in GitHub Actions — machine-agnostic,
|
|
79
|
+
no agent state, no multi-machine concern.
|
|
80
|
+
- **Layer 2 Sentinel fast-trigger:** MACHINE-LOCAL BY DESIGN. The `release-readiness-check`
|
|
81
|
+
job is single-owner (one dev agent runs it); dedup state lives in
|
|
82
|
+
`.instar/state/release-readiness.json`. No fenced lease needed — the dedup is advisory
|
|
83
|
+
and the boundary truth lives in `main` (not agent-local), so the worst case if two
|
|
84
|
+
agents ran it is a duplicate Attention raise (re-derived from `main`), never a lost
|
|
85
|
+
signal. On topic/machine transfer the new host re-derives from `main`. Documented in
|
|
86
|
+
the spec's Cross-machine posture section.
|
|
87
|
+
|
|
88
|
+
## 8. Rollback cost
|
|
89
|
+
|
|
90
|
+
- **Layer 1 workflow:** delete/disable `.github/workflows/release-fragment-gate.yml`
|
|
91
|
+
(or it stays warn-only = non-blocking by default — zero rollback urgency).
|
|
92
|
+
- **Layer 2 publish step:** the new step is `if: skip==true` and exits 0 always;
|
|
93
|
+
removing it is a one-line revert. It cannot break a real publish (it only runs on the
|
|
94
|
+
skip branch and never fails).
|
|
95
|
+
- **Sentinel fast-trigger:** config off-switch `fastTriggerOnGuideBlock: false` (no
|
|
96
|
+
restart-blocking); or revert the src change. The feature ships behind the existing
|
|
97
|
+
`release-readiness-check` job which is `enabled: false` by default, so on the fleet
|
|
98
|
+
it is inert until explicitly enabled.
|
|
99
|
+
- **Shared predicate / pre-push §3b broadening:** the broadening only makes the LOCAL
|
|
100
|
+
gate catch more (scripts/workflows); if it ever false-positives, `INSTAR_PRE_PUSH_SKIP=1`
|
|
101
|
+
is the existing escape and the predicate is a one-file revert.
|
|
102
|
+
|
|
103
|
+
No data migration, no agent-state repair, no hot-fix-release dependency. Every layer
|
|
104
|
+
fails safe (warn-only / signal-only / config-gated-off).
|
|
105
|
+
|
|
106
|
+
## Second-pass review (Phase 5 — required: touches a gate + a sentinel)
|
|
107
|
+
|
|
108
|
+
An independent reviewer audited the implementation against this artifact.
|
|
109
|
+
|
|
110
|
+
**Concern raised (MEDIUM, RESOLVED):** the shared predicate exempted
|
|
111
|
+
`.claude/hooks/**` and the four shipped `.claude/skills/<name>/` dirs — but those
|
|
112
|
+
ARE shipped to the fleet via `package.json` `files`, so a `.claude`-only behavior
|
|
113
|
+
change would have been wrongly exempt → re-opening the silent-skip for that path
|
|
114
|
+
class. **Fix applied:** the predicate now classifies `.claude/hooks/**` and the
|
|
115
|
+
shipped built-in `.claude/skills/{setup-wizard,secret-setup,autonomous,build}/`
|
|
116
|
+
paths as release-relevant (non-shipped `.claude/**` stays agent-local/exempt); the
|
|
117
|
+
anti-drift test's `KNOWN['.claude']` was corrected to `relevant` and path tests
|
|
118
|
+
added.
|
|
119
|
+
|
|
120
|
+
**Concern raised (LOW, RESOLVED):** the skills-code extension allowlist
|
|
121
|
+
(`.sh/.mjs/.js/.ts`) silently exempted `.cjs`/`.py`/`.json`. **Fix applied:** the
|
|
122
|
+
skill-path classifier now FAILS TOWARD RELEVANT — any non-doc file under a skill is
|
|
123
|
+
relevant; only a bare non-SKILL.md `*.md` outside `templates/` is exempt. Tests
|
|
124
|
+
added for `.cjs`/`.py`.
|
|
125
|
+
|
|
126
|
+
**Concern noted (LOW/INFO, ACCEPTED):** the bot exemption fires for any
|
|
127
|
+
`github-actions[bot]`-authored PR, not strictly the release-cut PR. Keyed on
|
|
128
|
+
authenticated identity (not a spoofable title — evasion test confirms), and Layer 2
|
|
129
|
+
+ the Sentinel backstop it. Acceptable; narrow only if a non-release bot ever opens
|
|
130
|
+
release-relevant PRs.
|
|
131
|
+
|
|
132
|
+
**Reviewer verdict on everything else: Concur — no material concerns.** Layer-1
|
|
133
|
+
security (base-ref load, read-only perms, no PR-head exec, env-passing), fail-closed
|
|
134
|
+
behavior, signal-only Layer-2 annotation (NUL-delimited argv, always exit 0),
|
|
135
|
+
publish-step gating, and the strictly-additive Sentinel fast-trigger were all
|
|
136
|
+
independently confirmed correct.
|