instar 1.3.1103 → 1.3.1105

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.
@@ -106,7 +106,7 @@ export function parseSafeYaml(input) {
106
106
  if (seqLines.length > 0 && seqLines.length === childLines.filter((l) => l.trim()).length) {
107
107
  const arr = [];
108
108
  for (const sl of seqLines) {
109
- const item = sl.replace(/^\s*-\s+/, '').trim();
109
+ const item = stripInlineComment(sl.replace(/^\s*-\s+/, '').trim()).trim();
110
110
  const v = parseScalar(item);
111
111
  if (typeof v !== 'string' && typeof v !== 'number' && typeof v !== 'boolean') {
112
112
  return { ok: false, error: `unsupported sequence item at "${key}"` };
@@ -139,8 +139,43 @@ export function parseSafeYaml(input) {
139
139
  }
140
140
  return { ok: true, data };
141
141
  }
142
+ /**
143
+ * Strip a YAML inline comment from a scalar value.
144
+ *
145
+ * YAML starts a comment at a `#` that is at the start of the value or preceded
146
+ * by whitespace, and never inside a quoted scalar. Before this existed, the
147
+ * parser kept the whole rest of the line, so
148
+ *
149
+ * approved: true # operator preapproval, topic 11960
150
+ *
151
+ * parsed as the STRING `"true # operator preapproval, topic 11960"`, and every
152
+ * gate testing `data.approved === true` silently concluded the spec was NOT
153
+ * approved. The comment that RECORDED the approval was what voided it.
154
+ *
155
+ * Deliberately conservative — a `#` not preceded by whitespace is part of the
156
+ * value (`url: http://host/p#frag`), and a `#` inside quotes is content.
157
+ */
158
+ function stripInlineComment(raw) {
159
+ let inStr = null;
160
+ for (let i = 0; i < raw.length; i++) {
161
+ const ch = raw[i];
162
+ if (inStr) {
163
+ if (ch === inStr)
164
+ inStr = null;
165
+ continue;
166
+ }
167
+ if (ch === '"' || ch === "'") {
168
+ inStr = ch;
169
+ continue;
170
+ }
171
+ if (ch === '#' && (i === 0 || /\s/.test(raw[i - 1]))) {
172
+ return raw.slice(0, i).replace(/\s+$/, '');
173
+ }
174
+ }
175
+ return raw;
176
+ }
142
177
  function parseInlineValue(raw) {
143
- const trimmed = raw.trim();
178
+ const trimmed = stripInlineComment(raw.trim()).trim();
144
179
  if (trimmed.startsWith('!')) {
145
180
  return { ok: false, error: 'YAML tags are not permitted' };
146
181
  }
@@ -1 +1 @@
1
- {"version":3,"file":"SafeYaml.js","sourceRoot":"","sources":["../../src/core/SafeYaml.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SafeYaml.js","sourceRoot":"","sources":["../../src/core/SafeYaml.ts"],"names":[],"mappings":"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"}
@@ -2,7 +2,7 @@
2
2
  "schemaVersion": 1,
3
3
  "generatedFrom": "source-tree",
4
4
  "registrySha256": "5413a0c6ef9ba2bda876b509d1c0bfebe450da3708cd5a5d627d6cb836012d58",
5
- "packageVersion": "1.3.1103",
5
+ "packageVersion": "1.3.1105",
6
6
  "guards": [
7
7
  {
8
8
  "ref": "docs/canonical-migration-contracts.json",
@@ -1,5 +1,5 @@
1
1
  {
2
- "sha256": "134f316424c9c178f1e9512d39504d10c88e6fad36e013596f2e25cff658488f",
2
+ "sha256": "15077c901800bcc841ad958a8a3268c271e7022484597215ee31c85c02f7ebbe",
3
3
  "registrySha256": "5413a0c6ef9ba2bda876b509d1c0bfebe450da3708cd5a5d627d6cb836012d58",
4
- "packageVersion": "1.3.1103"
4
+ "packageVersion": "1.3.1105"
5
5
  }
@@ -2,5 +2,5 @@
2
2
  "sha256": "5413a0c6ef9ba2bda876b509d1c0bfebe450da3708cd5a5d627d6cb836012d58",
3
3
  "articleCount": 82,
4
4
  "generatedFrom": "docs/STANDARDS-REGISTRY.md",
5
- "packageVersion": "1.3.1103"
5
+ "packageVersion": "1.3.1105"
6
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "instar",
3
- "version": "1.3.1103",
3
+ "version": "1.3.1105",
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",
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "$schema": "./builtin-manifest.schema.json",
3
3
  "schemaVersion": 1,
4
- "generatedAt": "2026-08-01T18:24:40.491Z",
5
- "instarVersion": "1.3.1103",
4
+ "generatedAt": "2026-08-01T18:38:43.377Z",
5
+ "instarVersion": "1.3.1105",
6
6
  "entryCount": 202,
7
7
  "entries": {
8
8
  "hook:session-start": {
@@ -2,7 +2,7 @@
2
2
  "schemaVersion": 1,
3
3
  "generatedFrom": "source-tree",
4
4
  "registrySha256": "5413a0c6ef9ba2bda876b509d1c0bfebe450da3708cd5a5d627d6cb836012d58",
5
- "packageVersion": "1.3.1103",
5
+ "packageVersion": "1.3.1105",
6
6
  "guards": [
7
7
  {
8
8
  "ref": "docs/canonical-migration-contracts.json",
@@ -1,5 +1,5 @@
1
1
  {
2
- "sha256": "134f316424c9c178f1e9512d39504d10c88e6fad36e013596f2e25cff658488f",
2
+ "sha256": "15077c901800bcc841ad958a8a3268c271e7022484597215ee31c85c02f7ebbe",
3
3
  "registrySha256": "5413a0c6ef9ba2bda876b509d1c0bfebe450da3708cd5a5d627d6cb836012d58",
4
- "packageVersion": "1.3.1103"
4
+ "packageVersion": "1.3.1105"
5
5
  }
@@ -2,5 +2,5 @@
2
2
  "sha256": "5413a0c6ef9ba2bda876b509d1c0bfebe450da3708cd5a5d627d6cb836012d58",
3
3
  "articleCount": 82,
4
4
  "generatedFrom": "docs/STANDARDS-REGISTRY.md",
5
- "packageVersion": "1.3.1103"
5
+ "packageVersion": "1.3.1105"
6
6
  }
@@ -0,0 +1,82 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: patch -->
5
+
6
+ ## What Changed
7
+
8
+ `pnpm install` failed on a fresh checkout of `main` and had done for some time. pnpm >= 11 refuses to run a dependency's install script without an explicit allowlist and exits non-zero while any remain unresolved; no allowlist was ever committed. Reproduced on v1.3.1071 with pnpm 11.5.1 from a branch off current `origin/main`: `exit 1`, `ERR_PNPM_IGNORED_BUILDS`, 13 ignored build scripts, nothing built.
9
+
10
+ This commits `pnpm-workspace.yaml` with an explicit boolean decision per package, and a unit-test guard.
11
+
12
+ Nine are allowed because their install step produces a real runtime artifact — a compiled native binding or a downloaded platform binary: `better-sqlite3`, `bufferutil`, `cloudflared`, `cpu-features`, `esbuild`, `onnxruntime-node`, `sharp`, `ssh2`, `utf-8-validate`. Three are declined because they produce nothing this project needs: `baileys` (engine-requirements check), `es5-ext` (prints a notice), `protobufjs`. Each entry carries an inline comment naming what its script actually does.
13
+
14
+ Two findings recorded while fixing it:
15
+
16
+ - **The failure was invisible to CI.** `ci.yml` installs with `npm ci` across all six jobs, so the pipeline never exercised the pnpm path that the bundled CLAUDE.md Quick Reference tells every agent to use. A green build proved nothing about it. The guard test exists because of this: without the pnpm path in CI, deleting the file or flipping a required entry to `false` would re-break the documented route without turning anything red.
17
+ - **The same allowlist in `package.json` under `pnpm.onlyBuiltDependencies` is silently ignored** by pnpm 11.5.1 — tried directly, install still exited 1 with all 13 still refused. The guard asserts that field is absent, so a later tidy-up cannot move the list somewhere that reads as configuration while doing nothing.
18
+
19
+ Deliberately not changed: which package manager this project standardises on. The docs say pnpm, CI uses npm, and both lock files are committed. That is an operator decision with consequences for contributors and the pipeline, and making the install work does not settle it. `packageManager` is also not added, because pinning it would make corepack authoritative over the `npm ci` jobs CI depends on — a regression risk for no benefit here. <!-- tracked: ACT-1613 -->
20
+
21
+ `scripts/ux-impact-lint.mjs` decides whether a PR counts as user-facing by matching
22
+ changed files against a hard-coded allowlist. That allowlist omitted
23
+ `src/scaffold/templates.ts` — the file the Agent Awareness Standard names as THE
24
+ user-awareness surface ("An agent that doesn't know about a capability effectively
25
+ doesn't have it"). A PR touching only that file matched nothing, hit
26
+ `allowlisted.length === 0`, and exited 0. The change that alters what every agent tells
27
+ its users required no UX declaration at all. `src/templates/` (hook and helper scripts)
28
+ was allowlisted; `src/scaffold/` was not.
29
+
30
+ Three edits, one defect:
31
+
32
+ 1. The `:25` allowlist gains `p === 'src/scaffold/templates.ts'` — the exact file the
33
+ standard names, in the exact exact-match style already used for two other files.
34
+ Deliberately **not** `startsWith('src/scaffold/')`: widening a gate beyond what a
35
+ standard names is a policy change nobody approved.
36
+ 2. The `:30` refactor-only exemption excludes that path too — rewriting agent-visible
37
+ text is never a pure refactor.
38
+ 3. The `:41` failure message now names the concept and lists the paths actually
39
+ searched. It previously read "UX Impact must quote a concrete string from the diff"
40
+ while searching only the allowlisted subset of the diff, so an author who correctly
41
+ quoted a real added line from an unlisted file was told something untrue about why
42
+ they failed.
43
+
44
+ The gating predicate at `:40` is untouched. `scripts/` is CI-only, is not bundled into
45
+ `dist/`, and is executed by no deployed agent, so no running agent's behaviour changes.
46
+
47
+ ## What to Tell Your User
48
+
49
+ None — internal change (no user-facing surface).
50
+
51
+ ## Summary of New Capabilities
52
+
53
+ None — internal change (no user-facing surface).
54
+
55
+ ## Evidence
56
+
57
+ - **Reproduced before fixing**, on a branch off freshly-fetched `origin/main` (3c90a8a65, v1.3.1071), with the pre-existing untracked placeholder file moved aside so the measurement reflected true fresh-checkout state: `pnpm install --frozen-lockfile </dev/null` → `exit=1`, `ERR_PNPM_IGNORED_BUILDS` listing all 13.
58
+ - **After the fix:** `exit=0`, and the native builds genuinely ran — ssh2 compiled and linked its optional crypto binding (`SOLINK_MODULE(target) Release/sshcrypto.node`, "Succeeded in building optional crypto binding").
59
+ - **Idempotent:** immediate re-run `exit=0` in 152ms.
60
+ - **Build unaffected:** `pnpm build` → `exit=0`.
61
+ - **Guard test red-green verified on every failure mode rather than assumed:** passes as written (4/4); with `pnpm-workspace.yaml` hidden → 3 failures, first being "pnpm-workspace.yaml is required"; with `sharp: true` flipped to `false` → 1 failure naming sharp specifically; restored → 4/4 again.
62
+
63
+ Verified against real commit `e29259c49`, which touches `src/scaffold/templates.ts` and
64
+ zero allowlisted paths (both confirmed by control counts):
65
+
66
+ | lint | result |
67
+ |---|---|
68
+ | shipping (`origin/main`) | `UX lint: out of scope`, exit 0 — gate skipped entirely |
69
+ | patched | engages, exit 1 on `UX-Impact: none` |
70
+ | patched, replaying PR #1813 | exit 0 — no regression on a real passing PR |
71
+
72
+ The static contradiction, with a control: `CLAUDE.md` names `src/scaffold/templates.ts`
73
+ as the user-awareness surface, while `ux-impact-lint.mjs` contained `scaffold` zero
74
+ times (control: `templates` = 2, so the search works and this is a true negative).
75
+
76
+ New test `tests/unit/ux-impact-lint-scaffold-scope.test.ts` covers both sides of the
77
+ boundary and was trip-tested by reverting the lint to `origin/main`: 3/3 pass with the
78
+ fix, 2 fail without it, and the internal-path control passes either way.
79
+
80
+ Known residual, not claimed as fixed: the allowlist remains a proxy for "user-facing"
81
+ and still omits `PostUpdateMigrator.ts`, skill bodies, and hook templates. This closes
82
+ one hole in one list; the list still has no owner and no review trigger.
@@ -0,0 +1,49 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: patch -->
5
+
6
+ ## What Changed
7
+
8
+ A spec whose approval was documented on the `approved:` line was silently unapproved. The frontmatter parser did not strip YAML inline comments, so
9
+
10
+ ```yaml
11
+ approved: true # operator authenticated preapproval, topic 11960, 2026-07-11
12
+ ```
13
+
14
+ parsed as the **string** `"true # operator authenticated preapproval, topic 11960, 2026-07-11"`. Every consumer testing `data.approved === true` — `StageTransitionValidator` above all — correctly concluded the flag was not `true` and refused the transition with `APPROVED_FLAG_MISSING`, on a file that visibly reads `approved: true`. The comment that recorded the approval was what voided it.
15
+
16
+ This adds `stripInlineComment()` in `src/core/SafeYaml.ts`, applied at **both** sites that interpret a scalar: `parseInlineValue` (`key: value # note`) and the block-sequence item path (`- item # note`). The identical defect existed in both; fixing only the one that surfaced would have left the class half-open.
17
+
18
+ The stripping is deliberately conservative, following the YAML rule rather than a looser one: a `#` begins a comment only at value-start or when preceded by whitespace, and never inside quotes. So `url: http://host/page#section` and `title: "sharp # sign"` are untouched. An earlier sketch cut at the first `#` unconditionally, which would have silently truncated URLs — that boundary is now the explicitly-tested half of the change.
19
+
20
+ Ordering note: the strip runs *before* the tag / anchor / flow-sequence checks in `parseInlineValue`, so `tags: [a, b] # note` no longer fails the `endsWith(']')` test and fall through to being read as a plain string. It cannot shadow the security rejections, because a value that *starts* with `!`, `&` or `*` is unaffected by comment-stripping.
21
+
22
+ Measured on `main` (53c2140b): 559 specs carry frontmatter, 522 carry an `approved:` line, and **9 of those carry an inline comment on it** — 1.7%. Those nine are not a random sample; they are the specs whose approvals were documented most carefully, which is what makes the failure mode worth closing at the parser rather than by hand-editing nine files.
23
+
24
+ ## What to Tell Your User
25
+
26
+ Nothing changes in how you work with me, and there is nothing for you to do.
27
+
28
+ If you have ever approved a design document by marking it approved and writing a short note on the same line saying who approved it and when, that note quietly cancelled the approval. The part of me that checks for approvals read the whole line as text instead of reading the yes-or-no answer, so it decided the document was never approved. The document said approved on screen and the checker disagreed, which made it look like nothing was wrong anywhere.
29
+
30
+ Nine documents were sitting in that state. They were not a random nine out of the five hundred that carry an approval mark. They were the ones where somebody took the trouble to record who approved it and when, which is the careful thing to do and was exactly what broke them.
31
+
32
+ That is now fixed, so those approvals count again and any future one written the same way will work. A note written next to a setting no longer swallows the setting.
33
+
34
+ ## Summary of New Capabilities
35
+
36
+ | Capability | How to Use |
37
+ |-----------|-----------|
38
+ | An approval marked with an explanatory note on the same line now counts as a real approval | Nothing to do — write the note however reads best, it no longer cancels the setting |
39
+ | Notes written beside any setting in a document header are ignored rather than swallowing the value | Nothing to do — applies to every setting, not only approvals |
40
+
41
+ ## Evidence
42
+
43
+ - **The bug, reproduced against the shipped parser before fixing:** loading `parseSafeYaml` from the installed dist and parsing `docs/specs/audit-convergence-enforcement.md` returned `approved` as `typeof string`, with `=== true` false, so the gate's verdict was `APPROVED_FLAG_MISSING`.
44
+ - **The fix, proved end-to-end on that same real file:** `approved` now parses as `true` (`typeof boolean`), with `approved-by` and `approved-date` intact — it passes the approved-flag gate it previously failed.
45
+ - **Test falsification, not assumption:** 13 new cases in `tests/unit/SafeYaml-inline-comments.test.ts`. Reverting `src/core/SafeYaml.ts` to its pre-change state and re-running gives **8 failed / 5 passed**. The 5 that pass either way are the conservative guards (URL fragment, `#` in double quotes, `#` in single quotes, `#` with no preceding space, no-comment values) — they prove existing behaviour is unchanged, and a test that passed without the fix would have proved nothing.
46
+ - **Every downstream consumer re-run green:** `StageTransitionValidator` (53), `ProjectRoundRunner` (27), `PlanDocParser` (9), `ProjectAutoAdvancePoller` (10), `convergence-gate-consistency` (23), `projects-advance-mergebase-wiring` (5), `spec-review-publish` (11) — **138 passed, 0 failed**.
47
+ - **`npx tsc --noEmit`** — clean.
48
+
49
+ Known limitation, flagged rather than fixed: escaped quotes inside a quoted scalar (`desc: 'it''s # here'`) would mis-track quote state. `parseScalar` already does no escape processing — it slices the outer quotes verbatim — so this is a pre-existing property of the deliberately narrow schema, not a regression, and no spec in the tree uses that shape.
@@ -0,0 +1,88 @@
1
+ # Side-Effects Review — Commit the pnpm dependency build allowlist
2
+
3
+ **Version / slug:** `pnpm-build-allowlist`
4
+ **Date:** `2026-07-30`
5
+ **Author:** `echo (instar-dev agent)`
6
+ **Second-pass reviewer:** `not required — no decision-point surface (see inventory)`
7
+
8
+ ## Summary of the change
9
+
10
+ `pnpm install` exits non-zero on a fresh checkout of current `main` (reproduced on v1.3.1071 / pnpm 11.5.1: `exit 1`, `ERR_PNPM_IGNORED_BUILDS`, 13 ignored build scripts) because pnpm >= 11 refuses to run a dependency's install script without an explicit allowlist, and no allowlist was committed. This adds `pnpm-workspace.yaml` recording an explicit boolean per package — 9 `true` (native binding compiled or platform binary downloaded), 3 `false` (engine check / printed notice / no artifact this project needs) — plus `tests/unit/pnpm-build-allowlist.test.ts` as a regression guard. Files touched: `pnpm-workspace.yaml` (new), `tests/unit/pnpm-build-allowlist.test.ts` (new), `docs/specs/pnpm-build-allowlist.eli16.md` (new), `upgrades/next/pnpm-build-allowlist.md` (new), this artifact.
11
+
12
+ Verified: install `exit 0` (native builds genuinely ran — ssh2 compiled its optional crypto binding), idempotent re-run `exit 0` in 152ms, `pnpm build` `exit 0`.
13
+
14
+ ## Decision-point inventory
15
+
16
+ This change adds **no** instar decision point. It does not gate information flow, block an action, filter a message, or constrain agent behavior. It is build-time dependency configuration consumed by pnpm, plus a test.
17
+
18
+ - `pnpm-workspace.yaml` → `allowBuilds` — **add** — build-time allowlist read by pnpm at install; no runtime surface, no instar code reads it.
19
+
20
+ ---
21
+
22
+ ## 1. Over-block
23
+
24
+ **What legitimate inputs does this change reject that it shouldn't?**
25
+
26
+ No block/allow surface over inputs — over-block not applicable in the messaging/gating sense.
27
+
28
+ The nearest analogue is the three `false` entries, which decline a build that *could* have run. Assessed individually against what each script actually does: `baileys` (`preinstall: node ./engine-requirements.js`) only asserts a minimum Node version; `es5-ext` (`postinstall: node -e "try{require('./_postinstall')}..."`) prints a notice and is written to swallow its own failure; `protobufjs` (`postinstall: node scripts/postinstall`) produces nothing this project consumes. If any of those judgements is wrong the symptom is a runtime failure in that specific package, and the remedy is a one-line flip to `true` with no migration. That is the residual risk and it is small and cheaply reversible.
29
+
30
+ ---
31
+
32
+ ## 2. Under-block
33
+
34
+ **What failure modes does this still miss?**
35
+
36
+ - **The real question is untouched.** The documented package manager (CLAUDE.md Quick Reference says `pnpm`) is not the one CI validates (`ci.yml` runs `npm ci` with `cache: npm` across all six jobs), and both `package-lock.json` and `pnpm-lock.yaml` are committed and can drift. This change makes the documented path *work*; it does not make it *tested*. A green pipeline still proves nothing about the pnpm route. <!-- tracked: ACT-1613 -->
37
+ - **No version pin.** `packageManager` is deliberately not added. Adding it would make corepack authoritative and could change behavior for the `npm ci` jobs that CI depends on — a real regression risk for zero benefit to this fix. So a contributor on a pnpm older than 11 sees different (though not failing) behavior. <!-- tracked: ACT-1613 -->
38
+ - **New dependencies won't be caught by the guard test.** A dependency added later with its own install script will re-trigger `ERR_PNPM_IGNORED_BUILDS` for whoever installs with pnpm. The guard asserts the current nine are present; it cannot know about a package that does not exist yet. Detecting that properly needs the pnpm path to run in CI, which is the item above.
39
+
40
+ ---
41
+
42
+ ## 3. Level-of-abstraction fit
43
+
44
+ Correct layer. The allowlist is pnpm's own configuration mechanism at its documented location, not an instar abstraction over it.
45
+
46
+ One placement finding worth recording: the same allowlist expressed as `pnpm.onlyBuiltDependencies` in `package.json` is **silently ignored** by pnpm 11.5.1 — tried it directly, and the install still exited 1 with all 13 scripts still reported ignored. Dead config that reads as authoritative is worse than no config, so the guard test asserts `package.json` does **not** carry that field. This is the sort of thing that would otherwise be "fixed" by a later tidy-up and silently regress.
47
+
48
+ ---
49
+
50
+ ## 4. Signal vs authority compliance
51
+
52
+ Not applicable — no authority and no signal. Per `docs/signal-vs-authority.md` the principle governs decision points that gate agent behavior; this is build configuration with no brittle logic and no blocking power over anything at runtime.
53
+
54
+ The one test added is an assertion over a committed file, which holds no authority over agent behavior either.
55
+
56
+ ---
57
+
58
+ ## 5. Interactions
59
+
60
+ - **npm is unaffected.** `pnpm-workspace.yaml` is a pnpm-specific filename; npm does not read it. CI's `npm ci` path is byte-for-byte unchanged.
61
+ - **No shadowing or double-firing.** Nothing else in the repo reads `allowBuilds`; no other check governs dependency build approval.
62
+ - **Adjacent postinstall preserved.** The repo's own root `postinstall` (`fix-better-sqlite3`) still runs and reported the native binary working. `prepare$ husky` still runs. Neither is affected by the dependency-level allowlist.
63
+ - **Pre-existing untracked placeholder.** A generated `pnpm-workspace.yaml` full of `set this to true or false` placeholders existed untracked in the local checkout. It was moved aside (preserved, not deleted) to reproduce true fresh-checkout state before measuring. Anyone carrying that local file will have it replaced by the committed one on merge, which is the desired outcome — the placeholder version does not resolve the error.
64
+
65
+ ---
66
+
67
+ ## 6. External surfaces
68
+
69
+ - **Visible to contributors and to agents onboarding to this repo**: the documented install command starts working. That is the entire user-facing effect.
70
+ - **No runtime behavior change** for any running agent. Nothing in `src/` is touched; no route, hook, template, scaffold, or gate changes. An already-installed agent is unaffected.
71
+ - **Timing / runtime conditions**: none. The file is read only at install time.
72
+ - **Supply-chain surface**: approving a build script permits that package to execute code at install time. Net effect versus today is a *reduction*: CI installs via npm, which runs all 13 with no gate, so 9-approved-3-declined leaves strictly less executing, with per-entry reasoning recorded inline.
73
+
74
+ ---
75
+
76
+ ## 7. Multi-machine posture (Cross-Machine Coherence)
77
+
78
+ **Machine-local BY DESIGN**, and correctly so. This is a file in the git repository consumed by a package manager on whichever machine performs an install. It is not agent state, so there is nothing to replicate, proxy on read, or merge; every machine gets the identical committed file by cloning. There is no notice, no durable per-machine state that could strand on topic transfer, and no generated URL.
79
+
80
+ Stated explicitly because the question exists to catch silent single-machine assumptions in *features*: this is not a feature, and the machine-local answer is structural rather than an oversight.
81
+
82
+ ---
83
+
84
+ ## 8. Rollback cost
85
+
86
+ Near-zero and immediate. `git revert` the commit: the file disappears and pnpm returns to its prior failing-but-harmless state. No release required beyond the normal one, no data migration, no agent state repair, nothing to un-migrate. Already-installed `node_modules` trees are unaffected either way.
87
+
88
+ If a specific approval turns out wrong, the narrower rollback is flipping that one entry to `false` (or the reverse) — a one-line change with no other consequence.
@@ -0,0 +1,180 @@
1
+ # Side-Effects Review — YAML inline comments in frontmatter values
2
+
3
+ **Version / slug:** `safeyaml-inline-comments`
4
+ **Date:** `2026-08-01`
5
+ **Author:** `Echo (instar-dev agent)`
6
+ **Second-pass reviewer:** `not required (Tier 1)`
7
+
8
+ ## Summary of the change
9
+
10
+ `src/core/SafeYaml.ts` did not strip YAML inline comments, so `approved: true # operator
11
+ preapproval, topic 11960` parsed as the STRING `"true # operator preapproval, topic 11960"`
12
+ rather than the boolean `true`. Every consumer testing `data.approved === true` therefore
13
+ concluded the spec was NOT approved — on a file that visibly reads `approved: true`. This
14
+ adds one helper, `stripInlineComment`, applied at the two sites where a scalar is
15
+ interpreted: `parseInlineValue` (`key: value # note`) and the block-sequence item path
16
+ (`- item # note`). Files touched: `src/core/SafeYaml.ts` (+39 LOC incl. its explanatory
17
+ comment) and a new `tests/unit/SafeYaml-inline-comments.test.ts` (13 cases).
18
+
19
+ ## Decision-point inventory
20
+
21
+ The parser itself makes no policy decision — it produces the values that decision points
22
+ read. It is upstream of three consumers, all pass-through here:
23
+
24
+ - `StageTransitionValidator` (`data.approved !== true` → `APPROVED_FLAG_MISSING`) — pass-through — receives a boolean where it previously received a string; its own logic is unchanged.
25
+ - `PlanDocParser` — pass-through — no approval surface; reads plan frontmatter.
26
+ - `ProjectRoundRunner` — pass-through — reads convergence/round frontmatter.
27
+
28
+ ---
29
+
30
+ ## 1. Over-block
31
+
32
+ **What legitimate inputs does this change reject that it shouldn't?**
33
+
34
+ None — the change removes characters from a value, it never rejects a document. The
35
+ equivalent risk is *over-stripping*: silently truncating a value that legitimately contains
36
+ `#`. Two concrete shapes were identified and are explicitly preserved:
37
+
38
+ - `url: http://host/page#section` — a `#` with no preceding whitespace is part of the value. Truncating here would corrupt a URL to `http://host/page` with no error.
39
+ - `title: "sharp # sign"` and `title: 'sharp # sign'` — a `#` inside quotes is content.
40
+
41
+ Both are covered by tests that pass before AND after the change (regression guards).
42
+
43
+ ---
44
+
45
+ ## 2. Under-block
46
+
47
+ **What failure modes does this still miss?**
48
+
49
+ - **Escaped quotes inside quoted scalars.** `desc: 'it''s # not a comment'` — the scanner treats the doubled `''` as close-then-open and would mis-track quote state. The pre-existing `parseScalar` does no escape processing either (it slices the outer quotes verbatim), so this is a pre-existing limitation of the narrow schema, not a new one. No spec in the tree uses escaped quotes in frontmatter.
50
+ - **A `#` preceded by a tab inside an otherwise unquoted value** is treated as a comment start (`/\s/` matches tab). That matches YAML.
51
+ - **Multi-line block scalars (`|`, `>`)** are untouched: comments are not stripped from block-scalar bodies. That is correct — inside a block scalar, `#` is literal content.
52
+
53
+ ---
54
+
55
+ ## 3. Level-of-abstraction fit
56
+
57
+ Correct layer. This is a **primitive** (a parser producing values), not a detector and not
58
+ an authority. The alternative placements are both worse: fixing it in
59
+ `StageTransitionValidator` would patch one consumer and leave `PlanDocParser` and
60
+ `ProjectRoundRunner` mis-parsing the same files, and fixing it at each call site would be
61
+ the "fixing one instance of a class is not fixing the class" anti-pattern. The fix belongs
62
+ where the value is produced, which is why both scalar-producing sites in the parser are
63
+ patched rather than only the one that surfaced the bug.
64
+
65
+ ---
66
+
67
+ ## 4. Signal vs authority compliance
68
+
69
+ **Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
70
+
71
+ - [x] No — this change has no block/allow surface.
72
+
73
+ The parser holds no blocking authority. It returns `Record<string, unknown>` and every
74
+ caller wraps it in its own schema validator. The change makes an existing authority
75
+ (`StageTransitionValidator`) receive *correct input*; it does not add, move, or weaken any
76
+ authority. Notably it does not make the gate more permissive in spirit — the gate's rule
77
+ ("frontmatter must carry `approved: true`") is unchanged, and a spec without an approval
78
+ flag is still refused exactly as before.
79
+
80
+ ---
81
+
82
+ ## 4b. Judgment-point check (Judgment Within Floors standard)
83
+
84
+ No new static heuristic at a competing-signals decision point. There are no competing live
85
+ signals here: "where does a YAML comment begin?" is an **enumerable invariant** fixed by the
86
+ YAML specification (a `#` at value-start or preceded by whitespace, outside quotes), not a
87
+ judgement call that varies with context. It is named directly in the helper's doc comment.
88
+
89
+ ---
90
+
91
+ ## 5. Interactions
92
+
93
+ - **Shadowing:** `stripInlineComment` runs FIRST in `parseInlineValue`, before the tag (`!`), anchor (`&`/`*`), flow-sequence (`[...]`) and flow-map (`{...}`) checks. This ordering is deliberate and was verified: a trailing comment after a flow sequence (`tags: [a, b] # note`) would otherwise fail the `endsWith(']')` test and be mis-parsed as a plain string. It cannot shadow the security rejections — a value that *starts* with `!`, `&` or `*` is unaffected by comment-stripping, so tags and anchors are still rejected.
94
+ - **Double-fire:** none. The helper is pure, has no side effects, and is called exactly once per scalar.
95
+ - **Races:** none. Pure function, no shared or persistent state.
96
+ - **Feedback loops:** none. Parsing does not feed back into any system that parses.
97
+
98
+ ---
99
+
100
+ ## 6. External surfaces
101
+
102
+ - **Other agents on the same machine:** no. Parsing is per-process and in-memory.
103
+ - **Install base:** yes, but only in the corrective direction — nine specs on `main` (of 522 carrying an `approved:` line) currently mis-parse and will begin parsing correctly. No spec can be depending on its approval flag being silently ignored.
104
+ - **External systems:** none.
105
+ - **Persistent state:** none written. The parser reads files and returns values; it never writes.
106
+ - **Timing / runtime conditions:** none.
107
+ - **Operator surface (Mobile-Complete Operator Actions):** no operator-facing actions added or touched.
108
+
109
+ ---
110
+
111
+ ## 6b. Operator-surface quality
112
+
113
+ No operator surface — not applicable. No dashboard renderer, approval page, or grant/secret
114
+ form is touched by this change.
115
+
116
+ ---
117
+
118
+ ## 7. Multi-machine posture (Cross-Machine Coherence)
119
+
120
+ **machine-local BY DESIGN**, and the reason is that there is no state to place: this is a
121
+ pure function over a string, evaluated independently on whichever machine happens to read
122
+ the file. The *inputs* (spec files) are already replicated by git, so every machine parses
123
+ identical bytes and — after this change — reaches identical values. Before the change every
124
+ machine also agreed, on the wrong answer; the change makes them agree on the right one.
125
+
126
+ Explicitly: it emits **no** user-facing notices (no one-voice gating needed), holds **no**
127
+ durable state (nothing to strand on topic transfer), and generates **no** URLs (nothing to
128
+ survive a machine boundary).
129
+
130
+ ---
131
+
132
+ ## 8. Rollback cost
133
+
134
+ - **Hot-fix release:** revert the commit, ship as the next patch. The change is one file plus one test file.
135
+ - **Data migration:** none. No persistent state is written or migrated.
136
+ - **Agent state repair:** none. No agent needs notifying or resetting.
137
+ - **User visibility:** during a rollback window the nine affected specs would return to reading as unapproved — i.e. back to today's behaviour. No new regression is introduced by rolling back.
138
+
139
+ Honest total: pure code change, revert-and-patch, no cleanup.
140
+
141
+ ## Conclusion
142
+
143
+ The review changed the shape of the fix twice. First, the initial patch touched only
144
+ `parseInlineValue`; the level-of-abstraction question surfaced that block-sequence items
145
+ carry the identical defect, so the second call site was added and tested. Second, the
146
+ over-block question forced the conservative rule to be stated precisely — an early sketch
147
+ stripped from the first `#` unconditionally, which would have silently truncated
148
+ `http://host/page#section`. That is now the explicitly-tested boundary.
149
+
150
+ The one residual limitation is escaped quotes inside quoted scalars (§2), which is
151
+ pre-existing in `parseScalar` and unreached by any spec in the tree. Flagged, not fixed —
152
+ widening escape handling is a larger change to the narrow-schema trade-off and does not
153
+ belong in a Tier-1 fix.
154
+
155
+ Clear to ship.
156
+
157
+ ---
158
+
159
+ ## Second-pass review (if required)
160
+
161
+ **Reviewer:** not required — Tier 1 (39 LOC, one file, no decision-point surface, no
162
+ persistent state, revert-and-patch rollback).
163
+
164
+ ---
165
+
166
+ ## Evidence pointers
167
+
168
+ - `tests/unit/SafeYaml-inline-comments.test.ts` — 13 cases; 8 fail against the pre-change parser, 5 (the conservative guards) pass both before and after. Falsification run: source reverted via `git stash`, suite re-run, 8 failed / 5 passed confirmed.
169
+ - Downstream consumers re-run green: `StageTransitionValidator` (53), `ProjectRoundRunner` (27), `PlanDocParser` (9), `ProjectAutoAdvancePoller` (10), `convergence-gate-consistency` (23), `projects-advance-mergebase-wiring` (5), `spec-review-publish` (11) — 138 passed, 0 failed.
170
+ - `npx tsc --noEmit` — clean.
171
+ - End-to-end on the real blocked file: `docs/specs/audit-convergence-enforcement.md` now yields `approved: true` (boolean) with `approved-by` and `approved-date` intact, so it passes the approved-flag gate it previously failed.
172
+
173
+ ---
174
+
175
+ ## Class-Closure Declaration (display-only mirror)
176
+
177
+ No agent-authored-artifact defect — not applicable. The defect is in ordinary source
178
+ (`src/core/SafeYaml.ts`), not in an LLM prompt, hook, config, skill, or standards text, and
179
+ the change adds no self-triggered controller (no loop, monitor, sentinel, reaper, scheduler,
180
+ or recovery path — the helper is a pure string function with no scheduling surface).
@@ -1,63 +0,0 @@
1
- # Upgrade Guide — vNEXT
2
-
3
- <!-- assembled-by: assemble-next-md -->
4
- <!-- bump: patch -->
5
-
6
- ## What Changed
7
-
8
- `scripts/ux-impact-lint.mjs` decides whether a PR counts as user-facing by matching
9
- changed files against a hard-coded allowlist. That allowlist omitted
10
- `src/scaffold/templates.ts` — the file the Agent Awareness Standard names as THE
11
- user-awareness surface ("An agent that doesn't know about a capability effectively
12
- doesn't have it"). A PR touching only that file matched nothing, hit
13
- `allowlisted.length === 0`, and exited 0. The change that alters what every agent tells
14
- its users required no UX declaration at all. `src/templates/` (hook and helper scripts)
15
- was allowlisted; `src/scaffold/` was not.
16
-
17
- Three edits, one defect:
18
-
19
- 1. The `:25` allowlist gains `p === 'src/scaffold/templates.ts'` — the exact file the
20
- standard names, in the exact exact-match style already used for two other files.
21
- Deliberately **not** `startsWith('src/scaffold/')`: widening a gate beyond what a
22
- standard names is a policy change nobody approved.
23
- 2. The `:30` refactor-only exemption excludes that path too — rewriting agent-visible
24
- text is never a pure refactor.
25
- 3. The `:41` failure message now names the concept and lists the paths actually
26
- searched. It previously read "UX Impact must quote a concrete string from the diff"
27
- while searching only the allowlisted subset of the diff, so an author who correctly
28
- quoted a real added line from an unlisted file was told something untrue about why
29
- they failed.
30
-
31
- The gating predicate at `:40` is untouched. `scripts/` is CI-only, is not bundled into
32
- `dist/`, and is executed by no deployed agent, so no running agent's behaviour changes.
33
-
34
- ## What to Tell Your User
35
-
36
- None — internal change (no user-facing surface).
37
-
38
- ## Summary of New Capabilities
39
-
40
- None — internal change (no user-facing surface).
41
-
42
- ## Evidence
43
-
44
- Verified against real commit `e29259c49`, which touches `src/scaffold/templates.ts` and
45
- zero allowlisted paths (both confirmed by control counts):
46
-
47
- | lint | result |
48
- |---|---|
49
- | shipping (`origin/main`) | `UX lint: out of scope`, exit 0 — gate skipped entirely |
50
- | patched | engages, exit 1 on `UX-Impact: none` |
51
- | patched, replaying PR #1813 | exit 0 — no regression on a real passing PR |
52
-
53
- The static contradiction, with a control: `CLAUDE.md` names `src/scaffold/templates.ts`
54
- as the user-awareness surface, while `ux-impact-lint.mjs` contained `scaffold` zero
55
- times (control: `templates` = 2, so the search works and this is a true negative).
56
-
57
- New test `tests/unit/ux-impact-lint-scaffold-scope.test.ts` covers both sides of the
58
- boundary and was trip-tested by reverting the lint to `origin/main`: 3/3 pass with the
59
- fix, 2 fail without it, and the internal-path control passes either way.
60
-
61
- Known residual, not claimed as fixed: the allowlist remains a proxy for "user-facing"
62
- and still omits `PostUpdateMigrator.ts`, skill bodies, and hook templates. This closes
63
- one hole in one list; the list still has no owner and no review trigger.