instar 1.3.881 → 1.3.882
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/scripts/instar-dev-precommit.js +34 -5
- package/skills/instar-dev/scripts/write-trace.mjs +3 -0
- package/src/data/builtin-manifest.json +2 -2
- package/upgrades/1.3.882.md +24 -0
- package/upgrades/decision-audit-trace-binding.eli16.md +9 -0
- package/upgrades/side-effects/decision-audit-trace-binding.md +72 -0
package/package.json
CHANGED
|
@@ -337,8 +337,11 @@ if (traceEntries.length === 0) {
|
|
|
337
337
|
}
|
|
338
338
|
|
|
339
339
|
// ─── Step 4.5: read the agent's DECLARED tier + branch ───────────────────
|
|
340
|
-
// The agent records its tier in the trace JSON.
|
|
341
|
-
//
|
|
340
|
+
// The agent records its tier in the trace JSON. Select the freshest trace that
|
|
341
|
+
// actually covers THIS staged change before reading its identity or tier. A
|
|
342
|
+
// merely-newer trace from another worktree/task must never label this decision
|
|
343
|
+
// audit (the feedback-class failure behind fb-2b24aa04-540).
|
|
344
|
+
// decideRequirementSet() factors the pure
|
|
342
345
|
// enforcement decision:
|
|
343
346
|
// - tier 1 → 'tier1-lite' (ELI16 + side-effects staged; no spec)
|
|
344
347
|
// - tier 2 / 3 → 'tier2-full' (the EXISTING full validation, unchanged)
|
|
@@ -347,8 +350,28 @@ if (traceEntries.length === 0) {
|
|
|
347
350
|
let declaredTier = null;
|
|
348
351
|
let tierReasoning = '';
|
|
349
352
|
let freshestTrace = null;
|
|
353
|
+
let freshestTraceEntry = null;
|
|
354
|
+
for (const entry of traceEntries) {
|
|
355
|
+
try {
|
|
356
|
+
const candidate = JSON.parse(fs.readFileSync(entry.file, 'utf8'));
|
|
357
|
+
const covered = new Set(candidate?.coveredFiles || []);
|
|
358
|
+
if (candidate?.phase === 'complete' && inScopeFiles.every((f) => covered.has(f))) {
|
|
359
|
+
freshestTrace = candidate;
|
|
360
|
+
freshestTraceEntry = entry;
|
|
361
|
+
break;
|
|
362
|
+
}
|
|
363
|
+
} catch {
|
|
364
|
+
// The full validation path below reports malformed attempts. They are not
|
|
365
|
+
// eligible to provide identity/tier metadata for this staged change.
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
if (!freshestTrace || !freshestTraceEntry) {
|
|
369
|
+
blockCommit(
|
|
370
|
+
inScopeFiles,
|
|
371
|
+
'No fresh complete trace covers this staged change. Run the /instar-dev skill for the files being committed.',
|
|
372
|
+
);
|
|
373
|
+
}
|
|
350
374
|
try {
|
|
351
|
-
freshestTrace = JSON.parse(fs.readFileSync(traceEntries[0].file, 'utf8'));
|
|
352
375
|
if (freshestTrace && (freshestTrace.tier === 1 || freshestTrace.tier === 2 || freshestTrace.tier === 3)) {
|
|
353
376
|
declaredTier = freshestTrace.tier;
|
|
354
377
|
}
|
|
@@ -360,7 +383,13 @@ try {
|
|
|
360
383
|
// path (the existing Step 5 loop will surface the malformed-JSON attempt).
|
|
361
384
|
}
|
|
362
385
|
|
|
363
|
-
const slug = (freshestTrace && (
|
|
386
|
+
const slug = (freshestTrace && (
|
|
387
|
+
freshestTrace.slug ||
|
|
388
|
+
freshestTrace.name ||
|
|
389
|
+
(typeof freshestTrace.artifactPath === 'string'
|
|
390
|
+
? path.basename(freshestTrace.artifactPath, path.extname(freshestTrace.artifactPath))
|
|
391
|
+
: null)
|
|
392
|
+
)) || 'unknown';
|
|
364
393
|
const decision = decideRequirementSet(declaredTier);
|
|
365
394
|
|
|
366
395
|
// ─── Step 4.55: causal autopsy (directive 2026-06-05) ───────────────────
|
|
@@ -480,7 +509,7 @@ if (belowFloor) {
|
|
|
480
509
|
// (The tests/lint requirement from the spec lives in the pre-PUSH gate, not
|
|
481
510
|
// here: this pre-COMMIT hook checks ARTIFACTS only.)
|
|
482
511
|
if (decision.requirementSet === 'tier1-lite') {
|
|
483
|
-
enforceTier1(freshestTrace,
|
|
512
|
+
enforceTier1(freshestTrace, freshestTraceEntry.file);
|
|
484
513
|
// enforceTier1 either passes through (process.exit(0)) or blockCommit()s.
|
|
485
514
|
}
|
|
486
515
|
|
|
@@ -212,6 +212,9 @@ const duplicateBuildCheck = readDuplicateBuildCheck();
|
|
|
212
212
|
|
|
213
213
|
const trace = {
|
|
214
214
|
version: toolchain ? 3 : 2, // v3 only when enriched; readers ignore unknown fields either way
|
|
215
|
+
// Stable work-item identity. The pre-commit decision audit consumes this;
|
|
216
|
+
// omitting it forced valid generated traces into the `unknown` bucket.
|
|
217
|
+
slug,
|
|
215
218
|
sessionId: process.env.INSTAR_SESSION_ID || process.env.CLAUDE_CODE_SESSION_ID || 'unknown',
|
|
216
219
|
timestamp,
|
|
217
220
|
artifactPath: artifact,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "./builtin-manifest.schema.json",
|
|
3
3
|
"schemaVersion": 1,
|
|
4
|
-
"generatedAt": "2026-07-
|
|
5
|
-
"instarVersion": "1.3.
|
|
4
|
+
"generatedAt": "2026-07-19T21:04:24.400Z",
|
|
5
|
+
"instarVersion": "1.3.882",
|
|
6
6
|
"entryCount": 202,
|
|
7
7
|
"entries": {
|
|
8
8
|
"hook:session-start": {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- assembled-by: assemble-next-md -->
|
|
4
|
+
<!-- bump: patch -->
|
|
5
|
+
|
|
6
|
+
## What Changed
|
|
7
|
+
|
|
8
|
+
- Persisted stable work-item identity in generated Instar development traces.
|
|
9
|
+
- Bound decision evidence to the staged change's matching trace before reading identity or tier, with a compatibility fallback for legacy traces.
|
|
10
|
+
- Added regressions for missing generated identity and a newer foreign `unknown` trace competing with the correct trace.
|
|
11
|
+
|
|
12
|
+
## What to Tell Your User
|
|
13
|
+
|
|
14
|
+
None — internal change (no user-facing surface).
|
|
15
|
+
|
|
16
|
+
## Summary of New Capabilities
|
|
17
|
+
|
|
18
|
+
None — internal change (no user-facing surface).
|
|
19
|
+
|
|
20
|
+
## Evidence
|
|
21
|
+
|
|
22
|
+
- Feedback: `fb-2b24aa04-540`
|
|
23
|
+
- Test: `tests/unit/instar-dev-precommit-audit-staging.test.ts`
|
|
24
|
+
- Test: `tests/unit/write-trace-tier.test.ts`
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Decision audit trace binding
|
|
2
|
+
|
|
3
|
+
Instar records a small decision artifact whenever its own development gate evaluates a change. That artifact is supposed to answer a simple future question: which work item was this decision about, and what change did the gate actually evaluate? The gate previously answered that question using the newest trace file written in the last hour. In a busy development environment, however, the newest trace can belong to another task or another attempted commit. That let a real change be recorded under `unknown` or under a foreign work-item name even though a correct trace for the staged files was present.
|
|
4
|
+
|
|
5
|
+
This repair changes the binding rule for the whole class, not just the reported instance. The canonical trace writer now persists the stable slug it already derives from the side-effects artifact. Before the gate reads a trace's tier, slug, or causal record, it requires that trace to be complete and to cover every staged behavior file. Newer unrelated or malformed traces are skipped. For older generated traces that predate the slug field, the gate derives the same stable identity from `artifactPath`. If no trace covers the staged change, the commit is refused with a direct explanation instead of emitting misleading evidence.
|
|
6
|
+
|
|
7
|
+
The important invariant is: development evidence is selected by scope first and recency second. A regression test creates two fresh traces—an older correct trace and a newer foreign `unknown` trace—and proves that the resulting decision record uses the correct work-item identity. This closes feedback item `fb-2b24aa04-540` and upgrades the development process so parallel work cannot recreate the same evidence-misbinding class.
|
|
8
|
+
|
|
9
|
+
There is no runtime or user-facing behavior change. The affected surface is the Instar source repository's pre-commit ceremony. Rollback is a normal code revert; no persisted runtime state or migration is involved.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Side-Effects Review — decision audit trace binding
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `decision-audit-trace-binding`
|
|
4
|
+
**Date:** `2026-07-19`
|
|
5
|
+
**Author:** `Instar Agent (instar-codey)`
|
|
6
|
+
**Second-pass reviewer:** `not required`
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
The trace writer now persists its derived slug, and the pre-commit gate selects the newest complete trace whose `coveredFiles` includes every staged behavior file before reading tier, slug, or class evidence. Legacy traces fall back to their artifact basename. Regression tests pin both causes from `fb-2b24aa04-540`: missing generated identity and a newer foreign trace.
|
|
11
|
+
|
|
12
|
+
## Decision-point inventory
|
|
13
|
+
|
|
14
|
+
- `scripts/instar-dev-precommit.js` trace selection — modified — deterministically binds evidence to the staged change and refuses when no binding exists.
|
|
15
|
+
|
|
16
|
+
## 1. Over-block
|
|
17
|
+
|
|
18
|
+
A legacy hand-written trace without `phase: complete` or without complete behavior-file coverage is now refused earlier. That is intentional: such a trace cannot honestly describe the staged decision.
|
|
19
|
+
|
|
20
|
+
## 2. Under-block
|
|
21
|
+
|
|
22
|
+
Two traces can both cover the same files; recency remains the tie-breaker. The trace SHA and artifact checks still validate the selected trace later in the gate.
|
|
23
|
+
|
|
24
|
+
## 3. Level-of-abstraction fit
|
|
25
|
+
|
|
26
|
+
The repair spans the canonical trace producer and the pre-commit evidence binder. It persists the already-derived artifact slug and reuses the existing `coveredFiles` contract instead of introducing another identity system.
|
|
27
|
+
|
|
28
|
+
## 4. Signal vs authority compliance
|
|
29
|
+
|
|
30
|
+
[docs/signal-vs-authority.md](../../docs/signal-vs-authority.md) applies. This is an enumerable integrity invariant: evidence either covers all staged behavior files or it does not. The deterministic gate correctly holds blocking authority over an invalid development commit.
|
|
31
|
+
|
|
32
|
+
## 4b. Judgment-point check
|
|
33
|
+
|
|
34
|
+
No competing-signals judgment is introduced. Scope membership is an exact set-containment invariant.
|
|
35
|
+
|
|
36
|
+
## 5. Interactions
|
|
37
|
+
|
|
38
|
+
The selector runs before Tier-1 branching and before the existing full trace validation. It cannot double-fire. Full artifact, SHA, and spec validation remain unchanged. Parallel worktrees may leave traces behind, but those traces no longer influence unrelated staged changes.
|
|
39
|
+
|
|
40
|
+
## 6. External surfaces
|
|
41
|
+
|
|
42
|
+
No runtime, user, operator, network, or API surface changes. The persistent decision audit becomes more accurate.
|
|
43
|
+
|
|
44
|
+
## 6b. Operator-surface quality
|
|
45
|
+
|
|
46
|
+
No operator surface — not applicable.
|
|
47
|
+
|
|
48
|
+
## 7. Multi-machine posture
|
|
49
|
+
|
|
50
|
+
Machine-local by design: pre-commit traces and staged changes belong to one development worktree on one machine. It emits no user notice, creates no transferable runtime state, and generates no URL.
|
|
51
|
+
|
|
52
|
+
## 8. Rollback cost
|
|
53
|
+
|
|
54
|
+
Pure development-tooling code change. Revert and ship; no migration or agent-state repair is required.
|
|
55
|
+
|
|
56
|
+
## Conclusion
|
|
57
|
+
|
|
58
|
+
The class review found the missing standard was scope-bound evidence selection, and the process gap was reading identity from the newest trace before proving it described the staged files. The code and regression ratchet now enforce scope-first, recency-second selection. Clear to ship.
|
|
59
|
+
|
|
60
|
+
## Second-pass review
|
|
61
|
+
|
|
62
|
+
Not required: this does not touch runtime messaging, sessions, sentinels, guards, or watchdogs.
|
|
63
|
+
|
|
64
|
+
## Evidence pointers
|
|
65
|
+
|
|
66
|
+
- `tests/unit/instar-dev-precommit-audit-staging.test.ts`
|
|
67
|
+
- `tests/unit/write-trace-tier.test.ts`
|
|
68
|
+
- Feedback `fb-2b24aa04-540`
|
|
69
|
+
|
|
70
|
+
## Class-Closure Declaration (display-only mirror)
|
|
71
|
+
|
|
72
|
+
`defectClass: claim-vs-evidence`, `closure: guard`, `guardEvidence: { enforcementType: gate, citation: scripts/instar-dev-precommit.js#freshestTraceEntry, howCaught: the gate selects only a complete trace covering every staged behavior file before using its slug or tier, so a newer foreign or unknown trace cannot label the decision }`.
|