instar 1.3.1152 → 1.3.1153
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/data/standards-guard-index.json +1 -1
- package/dist/data/standards-guard-index.meta.json +2 -2
- package/dist/data/standards-registry.meta.json +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +2 -2
- package/src/data/standards-guard-index.json +1 -1
- package/src/data/standards-guard-index.meta.json +2 -2
- package/src/data/standards-registry.meta.json +1 -1
- package/upgrades/1.3.1153.md +62 -0
- package/upgrades/side-effects/atomic-writes-method-scope.md +152 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"generatedFrom": "source-tree",
|
|
4
4
|
"registrySha256": "81b53363a440e832672618965540b3e507ae0d93adcc67ec2b93daf7933b3ab4",
|
|
5
|
-
"packageVersion": "1.3.
|
|
5
|
+
"packageVersion": "1.3.1153",
|
|
6
6
|
"guards": [
|
|
7
7
|
{
|
|
8
8
|
"ref": "docs/audits/phase-b/f10-triage.md",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"sha256": "
|
|
2
|
+
"sha256": "c9fe9271930f52c79239f9b43e4d3c873717dc1dd98744525290c8ccba4f07bf",
|
|
3
3
|
"registrySha256": "81b53363a440e832672618965540b3e507ae0d93adcc67ec2b93daf7933b3ab4",
|
|
4
|
-
"packageVersion": "1.3.
|
|
4
|
+
"packageVersion": "1.3.1153"
|
|
5
5
|
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "./builtin-manifest.schema.json",
|
|
3
3
|
"schemaVersion": 1,
|
|
4
|
-
"generatedAt": "2026-08-15T01:
|
|
5
|
-
"instarVersion": "1.3.
|
|
4
|
+
"generatedAt": "2026-08-15T01:31:14.741Z",
|
|
5
|
+
"instarVersion": "1.3.1153",
|
|
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": "81b53363a440e832672618965540b3e507ae0d93adcc67ec2b93daf7933b3ab4",
|
|
5
|
-
"packageVersion": "1.3.
|
|
5
|
+
"packageVersion": "1.3.1153",
|
|
6
6
|
"guards": [
|
|
7
7
|
{
|
|
8
8
|
"ref": "docs/audits/phase-b/f10-triage.md",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"sha256": "
|
|
2
|
+
"sha256": "c9fe9271930f52c79239f9b43e4d3c873717dc1dd98744525290c8ccba4f07bf",
|
|
3
3
|
"registrySha256": "81b53363a440e832672618965540b3e507ae0d93adcc67ec2b93daf7933b3ab4",
|
|
4
|
-
"packageVersion": "1.3.
|
|
4
|
+
"packageVersion": "1.3.1153"
|
|
5
5
|
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- assembled-by: assemble-next-md -->
|
|
4
|
+
<!-- bump: patch -->
|
|
5
|
+
|
|
6
|
+
## What Changed
|
|
7
|
+
|
|
8
|
+
The atomic-writes consistency test could not detect the defect it exists to detect.
|
|
9
|
+
|
|
10
|
+
Measured rather than argued: a bare `fs.writeFileSync` of durable session state, inserted into
|
|
11
|
+
`saveSession` — a DECLARED method of a DECLARED module — passed all 21 of its assertions.
|
|
12
|
+
|
|
13
|
+
Three causes, all fixed:
|
|
14
|
+
|
|
15
|
+
1. **Scoping.** `inSaveMethod` was set when a method NAME appeared on a line and never reset, while
|
|
16
|
+
`hasWriteFile`/`hasRename` were re-zeroed at each occurrence. Only the window from the LAST name
|
|
17
|
+
mention to EOF reached the assertion — 125 of 617 lines (20%) in `StateManager.ts`, leaving three
|
|
18
|
+
of its four declared methods structurally unreachable. Bodies are now brace-matched per method.
|
|
19
|
+
2. **File-scope substring checks.** `source.includes('renameSync')` and `source.includes('.tmp')` are
|
|
20
|
+
satisfied by one occurrence anywhere in the file, comments included. Pairing is now per body.
|
|
21
|
+
3. **Silent declaration rot.** A missing file was `it.skip`ped and a missing method never set the
|
|
22
|
+
flag, so a rename dropped a module out of coverage without a sound. Both are failures now — and
|
|
23
|
+
enabling that found two immediately: `saveState` has ZERO occurrences in `StateManager.ts` and in
|
|
24
|
+
`QuotaTracker.ts`. QuotaTracker's real writer, `updateState()`, is atomic and had never been
|
|
25
|
+
verified by this test. The declared list is corrected here.
|
|
26
|
+
|
|
27
|
+
**Delegation.** `StateManager` funnels every write through a private `atomicWrite()`. A naive
|
|
28
|
+
per-method rule would have failed the best-written module in the set for being well written, so one
|
|
29
|
+
level of `this.helper()` delegation is resolved and the funnel is what gets verified — which means
|
|
30
|
+
`StateManager`'s writes are now genuinely checked, where before nothing checked them.
|
|
31
|
+
|
|
32
|
+
Added `tests/helpers/atomicWriteScope.ts` (`stripComments`, `methodBodies`, `delegateTargets`,
|
|
33
|
+
`classifyMethod`) and `tests/unit/atomic-write-scope.test.ts`.
|
|
34
|
+
|
|
35
|
+
**Declared open in the source:** the module list is curated at 7 entries and says nothing about the
|
|
36
|
+
hundreds of other files under `src/` that call `writeFileSync`; delegation resolves one level within
|
|
37
|
+
one file; only `writeFileSync`/`renameSync` are recognised.
|
|
38
|
+
|
|
39
|
+
**The production code is atomic** everywhere the check now looks. This fixes a weak instrument, not a
|
|
40
|
+
live corruption bug.
|
|
41
|
+
|
|
42
|
+
## What to Tell Your User
|
|
43
|
+
|
|
44
|
+
None — internal change (no user-facing surface).
|
|
45
|
+
|
|
46
|
+
## Summary of New Capabilities
|
|
47
|
+
|
|
48
|
+
None — internal change (no user-facing surface).
|
|
49
|
+
|
|
50
|
+
## Evidence
|
|
51
|
+
|
|
52
|
+
- `tests/unit/atomic-write-scope.test.ts` — 18/18 green (6 defect cases, 6 over-block controls, 6 primitives).
|
|
53
|
+
- `tests/unit/atomic-writes-consistency.test.ts` — 32/32 green against the real tree.
|
|
54
|
+
- **Both-directions proof in ONE worktree**, shipped check restored from git alongside the new one so
|
|
55
|
+
subject and control share a boundary: shipped → **21/21 PASSED** against the mutation; new →
|
|
56
|
+
**1 failed / 31 passed**, naming file, method, deciding body and line. `src/core/StateManager.ts`
|
|
57
|
+
restored byte-exact (sha match, zero markers, zero stray files).
|
|
58
|
+
- Six over-block controls pass under BOTH behaviours — genuine funnel delegation, in-body
|
|
59
|
+
tmp-then-rename, a method that writes nothing, a commented-out write, a call site vs a declaration,
|
|
60
|
+
and worst-verdict-wins across duplicate declarations.
|
|
61
|
+
- `tsc --noEmit` exit 0 — with the boundary stated: `tsconfig.json` excludes `tests`, so that run says
|
|
62
|
+
nothing about these files.
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Side-Effects Review — atomic-writes check scopes to method bodies
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `atomic-writes-method-scope`
|
|
4
|
+
**Date:** `2026-08-15`
|
|
5
|
+
**Author:** `echo`
|
|
6
|
+
**Second-pass reviewer:** `not required — Tier 1. Test-only change; no file under src/, scripts/, .husky/ or skills/ is touched, so there is no runtime path and no shipped behaviour. The change makes an existing check stricter and adds no authority.`
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
`tests/unit/atomic-writes-consistency.test.ts` verifies that state-writing modules use
|
|
11
|
+
write-to-tmp-then-rename, so a crash mid-write cannot leave a truncated state file. **It could not
|
|
12
|
+
detect the defect it exists to detect.**
|
|
13
|
+
|
|
14
|
+
Measured, not argued — a bare `fs.writeFileSync` of durable session state inserted into
|
|
15
|
+
`saveSession`, a DECLARED method of a DECLARED module:
|
|
16
|
+
|
|
17
|
+
| check | verdict against that mutation |
|
|
18
|
+
|---|---|
|
|
19
|
+
| shipped | **21/21 PASSED** |
|
|
20
|
+
| this change | **1 failed / 31 passed**, naming file, method, deciding body, line |
|
|
21
|
+
|
|
22
|
+
Both runs were made in the SAME worktree against the SAME mutated source, with the shipped check
|
|
23
|
+
restored from git alongside the new one — subject and control share a boundary rather than being
|
|
24
|
+
compared across two checkouts.
|
|
25
|
+
|
|
26
|
+
Three causes, all fixed:
|
|
27
|
+
|
|
28
|
+
1. **Scoping.** `inSaveMethod` was set when a method NAME appeared on a line and never reset, while
|
|
29
|
+
`hasWriteFile`/`hasRename` were re-zeroed at each occurrence. Only the window from the LAST name
|
|
30
|
+
mention to EOF survived to the assertion — measured at **125 of 617 lines (20%)** in
|
|
31
|
+
`StateManager.ts`, leaving three of its four declared methods structurally unreachable. Within
|
|
32
|
+
that window the booleans were file-scope, so a rename in one method vouched for a write in another.
|
|
33
|
+
2. **File-scope substring checks.** `source.includes('renameSync')` and `source.includes('.tmp')` are
|
|
34
|
+
satisfied by one occurrence anywhere, comments included.
|
|
35
|
+
3. **Silent declaration rot.** A missing file was `it.skip`ped; a missing method simply never set the
|
|
36
|
+
flag. Both are failures now.
|
|
37
|
+
|
|
38
|
+
## What enabling (3) immediately found
|
|
39
|
+
|
|
40
|
+
**Two of the ten declared (module, method) pairs name methods that do not exist.** `saveState` has
|
|
41
|
+
ZERO occurrences in `src/core/StateManager.ts` and ZERO in `src/monitoring/QuotaTracker.ts` — verified
|
|
42
|
+
by grep with a control (`saveSession(`, `appendEvent(`, `persistUsers(` all found). QuotaTracker's
|
|
43
|
+
real writer is `updateState()`, which is correctly atomic and had never been verified by this test.
|
|
44
|
+
The declared list is corrected in the same change.
|
|
45
|
+
|
|
46
|
+
## Decision-point inventory
|
|
47
|
+
|
|
48
|
+
- `tests/helpers/atomicWriteScope.ts` — ADD. `stripComments` (quote-aware, line-count preserving),
|
|
49
|
+
`methodBodies` (brace-matched, string-aware, declaration-vs-call aware), `delegateTargets`,
|
|
50
|
+
`classifyMethod`.
|
|
51
|
+
- `tests/unit/atomic-writes-consistency.test.ts` — REWRITTEN to per-method assertions; declared list
|
|
52
|
+
corrected; missing file/method now fail; anti-vacuity assertion added.
|
|
53
|
+
- `tests/unit/atomic-write-scope.test.ts` — ADD. 18 tests pinning the primitives and both directions.
|
|
54
|
+
- No file under `src/`, `scripts/`, `.husky/` or `skills/` is touched. No runtime decision added.
|
|
55
|
+
|
|
56
|
+
## 1. Over-block
|
|
57
|
+
|
|
58
|
+
**The dominant risk, and it nearly bit me.** The obvious fix — require a rename in each declared
|
|
59
|
+
method's own body — would have FAILED on `StateManager`, the best-written module in the set, because
|
|
60
|
+
it routes every write through a private `atomicWrite()` funnel and its save methods contain no write
|
|
61
|
+
call at all. Failing the single-funnel pattern this codebase argues for everywhere else would be a
|
|
62
|
+
false red on exemplary code.
|
|
63
|
+
|
|
64
|
+
So one level of `this.helper()` delegation is resolved and the funnel is what gets verified — which
|
|
65
|
+
also means `StateManager`'s writes are now genuinely checked, where previously nothing checked them.
|
|
66
|
+
|
|
67
|
+
Six controls, each with a test, all passing under BOTH the old and new behaviour:
|
|
68
|
+
|
|
69
|
+
- delegation to a genuine atomic funnel → `atomic-via-funnel`, not a violation;
|
|
70
|
+
- in-body tmp-then-rename → `atomic-inline`;
|
|
71
|
+
- a method that legitimately writes nothing → `no-write`, no invented violation;
|
|
72
|
+
- a commented-out write is not a write;
|
|
73
|
+
- a CALL site (`this.saveSession({...})` inside another method) is not a declaration — treating it as
|
|
74
|
+
one is precisely how the old flag conflated two methods;
|
|
75
|
+
- an unbalanced brace yields no body rather than a wrong region, so a syntax error elsewhere cannot
|
|
76
|
+
become a false verdict here.
|
|
77
|
+
|
|
78
|
+
**Verified against the real tree: 32/32 green.** The production code is atomic everywhere the check
|
|
79
|
+
now looks, including through the funnel.
|
|
80
|
+
|
|
81
|
+
**A defect in my own helper, caught by these controls before it shipped:** the first `methodBodies`
|
|
82
|
+
required a declaration at line start. That works on real source (which indents declarations) and
|
|
83
|
+
returned `found: false` for every hand-written fixture — so five tests failed loudly rather than
|
|
84
|
+
passing vacuously. The matcher now decides by the PRECEDING token (start / `{` / `}` / `;` after
|
|
85
|
+
skipping modifiers), which rejects `this.save(` and `helper(save(1))` as calls while accepting a
|
|
86
|
+
declaration that does not begin its own line.
|
|
87
|
+
|
|
88
|
+
## 2. Under-block
|
|
89
|
+
|
|
90
|
+
Stated in the source rather than implied:
|
|
91
|
+
|
|
92
|
+
- **Population.** The module list is CURATED and holds 7 entries. Hundreds of files under `src/` call
|
|
93
|
+
`writeFileSync`; this test says nothing about any of them. A heuristic sweep suggested a state-writing
|
|
94
|
+
population in the low hundreds, but that heuristic missed 2 of the 7 KNOWN-good modules, so it is not
|
|
95
|
+
a defect count and is not quoted as one. Widening the population is separate work with real
|
|
96
|
+
over-block risk and is deliberately not attempted here.
|
|
97
|
+
- **Delegation depth.** One level, one file. A helper calling another helper, or an imported writer,
|
|
98
|
+
is not resolved — that needs a symbol graph, not text.
|
|
99
|
+
- **Write vocabulary.** Only `writeFileSync`/`renameSync`. A module writing via a stream, `fs.promises`,
|
|
100
|
+
or a third-party helper is invisible.
|
|
101
|
+
|
|
102
|
+
## 3. Level-of-abstraction fit
|
|
103
|
+
|
|
104
|
+
Same layer as the existing check — source-text analysis in a unit test, no AST, no type information,
|
|
105
|
+
no new dependency. The brace matcher is the minimum needed to answer "which method is this line in?",
|
|
106
|
+
which is the question the original flag was trying and failing to answer.
|
|
107
|
+
|
|
108
|
+
## 4. Signal vs authority compliance
|
|
109
|
+
|
|
110
|
+
A test, not a runtime authority. It gates CI only. It gained teeth (it can now fail) but no new
|
|
111
|
+
decision-making power over agent behaviour.
|
|
112
|
+
|
|
113
|
+
## 5. Interactions
|
|
114
|
+
|
|
115
|
+
- Runs in the existing unit shards; no new script, no lint-chain entry, no CI wiring change.
|
|
116
|
+
- `tsc --noEmit` exit 0 — **but stated honestly: `tsconfig.json` excludes `tests`, so that run says
|
|
117
|
+
nothing about these files.** Their correctness is evidenced by the suite passing, not by the compiler.
|
|
118
|
+
- No source module, route, config key, or state file touched.
|
|
119
|
+
|
|
120
|
+
## 6. External surfaces
|
|
121
|
+
|
|
122
|
+
None. Developer tooling. The Agent Awareness Standard does not apply — no agent capability is added.
|
|
123
|
+
|
|
124
|
+
## 7. Multi-machine posture (Cross-Machine Coherence)
|
|
125
|
+
|
|
126
|
+
**Machine-local by design, and correct.** A unit test reads files in one checkout and returns an exit
|
|
127
|
+
code. No durable state, no user-facing notice, no generated URL, no runtime decision — nothing to
|
|
128
|
+
replicate, merge on read, or strand on a topic transfer. Every machine runs it over its own checkout
|
|
129
|
+
of the same tracked source and reaches the same verdict; determinism comes from the source tree, not
|
|
130
|
+
from coordination.
|
|
131
|
+
|
|
132
|
+
## 8. Rollback cost
|
|
133
|
+
|
|
134
|
+
`git revert` of three test files. No migration, no state, no deployed artifact, no runtime impact.
|
|
135
|
+
|
|
136
|
+
## Conclusion
|
|
137
|
+
|
|
138
|
+
Ship. A check that could not fail on its own subject now fails on it, two stale declarations are
|
|
139
|
+
repaired, the best-written module in the set is verified for the first time, and the limits are named
|
|
140
|
+
in the source rather than implied.
|
|
141
|
+
|
|
142
|
+
## Evidence pointers
|
|
143
|
+
|
|
144
|
+
- `tests/unit/atomic-write-scope.test.ts` — 18/18 green (6 defect cases, 6 over-block controls, 6 primitives).
|
|
145
|
+
- `tests/unit/atomic-writes-consistency.test.ts` — 32/32 green against the real tree.
|
|
146
|
+
- **Both-directions proof in ONE worktree:** shipped check vs the mutation → 21/21 PASSED; new check
|
|
147
|
+
vs the SAME mutation → 1 failed / 31 passed. `src/core/StateManager.ts` restored byte-exact
|
|
148
|
+
(sha match, zero probe markers, zero stray files).
|
|
149
|
+
- Stale declarations verified by grep with a control that fired.
|
|
150
|
+
- `tsc --noEmit` exit 0 (boundary stated above: tests are excluded from that config).
|
|
151
|
+
- Tier **1** declared: `classifyTier` reports riskFloor 1 with no safety-invariant match, and `tests/`
|
|
152
|
+
is outside `inScope()`, so the size heuristic contributes nothing either.
|