instar 1.3.1048 → 1.3.1049

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.
@@ -2,5 +2,5 @@
2
2
  "sha256": "b75c147afd1f5a9843ca4eac372159f3623f24731fe63b2f59e48043ae488af9",
3
3
  "articleCount": 82,
4
4
  "generatedFrom": "docs/STANDARDS-REGISTRY.md",
5
- "packageVersion": "1.3.1048"
5
+ "packageVersion": "1.3.1049"
6
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "instar",
3
- "version": "1.3.1048",
3
+ "version": "1.3.1049",
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",
@@ -34,6 +34,7 @@ import { classifyTier, decideRequirementSet } from './lib/classify-tier.mjs';
34
34
  import { recognizeConvergence } from './lib/convergence-recognition.mjs';
35
35
  import { isOperatorSurfaceFile, artifactAddressesOperatorSurfaceQuality, isAuthorizationSurfaceFile, artifactAddressesAgentProposesApproves, operatorSurfaceRequiresRawInput } from './lib/operator-surface.mjs';
36
36
  import { selfActionDeclarationVerdict } from './lib/self-action-detect.mjs';
37
+ import { isKnownInlineCodeEnumReference } from './lib/markdown-code-identifier.mjs';
37
38
  import { validateAuditReport, parseFrontmatter } from './write-audit-convergence.mjs';
38
39
  import { scanForSecrets } from './audit-secret-patterns.mjs';
39
40
 
@@ -843,9 +844,13 @@ if (staged.includes(spec) && !staged.includes(eli16Rel)) {
843
844
  // `deferrals-tracked` field). Override via INSTAR_DEV_ALLOW_ORPHAN_DEFERRALS=1
844
845
  // (logged for visibility).
845
846
  //
846
- // Detector patterns intentionally conservative false-positives are cheaper
847
- // than false-negatives here. The author can either link a tracker or rephrase
848
- // the sentence to not promise a deferral.
847
+ // Detector patterns intentionally remain conservative over the complete
848
+ // document: headings, callouts, indented text, and standalone inline-code words
849
+ // can all carry real scope decisions. The one structural exclusion is a
850
+ // reference list for the shipped MigrationPerEntryAction CLOSED ENUM. A lone
851
+ // `deferred-in-flight` remains visible; the exemption requires another known
852
+ // enum member on the same line. This validates structured input rather than
853
+ // inferring meaning from Markdown or identifier shape.
849
854
  // Patterns: { regex, requireUnnegated } — when requireUnnegated is true,
850
855
  // we skip the match if the immediately-preceding chars contain "no ", "non-",
851
856
  // "non ", "non", or "un" (so "no deferrals" / "non-deferred" / "undeferred"
@@ -883,6 +888,7 @@ function findOrphanDeferrals(content) {
883
888
  let m;
884
889
  while ((m = regex.exec(content)) !== null) {
885
890
  const start = m.index;
891
+ if (isKnownInlineCodeEnumReference(content, start, start + m[0].length)) continue;
886
892
  if (requireUnnegated) {
887
893
  // Look at up to 8 chars immediately before the match. Treat
888
894
  // matches preceded by "no ", "non-", "non ", "un" as legitimate
@@ -0,0 +1,130 @@
1
+ /** The shipped MigrationPerEntryAction closed enum from MigrationLedger.ts. */
2
+ export const MIGRATION_LEDGER_ACTION_VALUES = Object.freeze([
3
+ 'migrated',
4
+ 'forked',
5
+ 'renamed',
6
+ 'skipped',
7
+ 'failed',
8
+ 'deferred-in-flight',
9
+ ]);
10
+
11
+ /**
12
+ * Return true only when a candidate range is a reference to the shipped
13
+ * MigrationPerEntryAction enum: it must sit inside an inline-code span whose
14
+ * complete value is in the closed enum, and the same line must enumerate at
15
+ * least one other closed-enum member in its own inline-code span.
16
+ *
17
+ * A lone `deferred-in-flight` may still be an authorial disposition and remains
18
+ * visible to the caller. Fenced blocks, headings, blockquotes, indented text,
19
+ * standalone inline-code words, escaped backticks, and unknown identifiers also
20
+ * remain visible. This validates already-structured input against a fixed enum;
21
+ * it does not infer intent from identifier shape.
22
+ */
23
+ export function isKnownInlineCodeEnumReference(markdown, candidateStart, candidateEnd) {
24
+ if (
25
+ typeof markdown !== 'string'
26
+ || !Number.isInteger(candidateStart)
27
+ || !Number.isInteger(candidateEnd)
28
+ || candidateStart < 0
29
+ || candidateEnd <= candidateStart
30
+ || candidateEnd > markdown.length
31
+ ) {
32
+ return false;
33
+ }
34
+
35
+ const isEscaped = (index) => {
36
+ let slashes = 0;
37
+ for (let i = index - 1; i >= 0 && markdown[i] === '\\'; i -= 1) slashes += 1;
38
+ return slashes % 2 === 1;
39
+ };
40
+
41
+ const fencedRanges = [];
42
+ let fence = null;
43
+ let lineStart = 0;
44
+ while (lineStart < markdown.length) {
45
+ const newline = markdown.indexOf('\n', lineStart);
46
+ const lineEnd = newline >= 0 ? newline + 1 : markdown.length;
47
+ const line = markdown.slice(lineStart, newline >= 0 ? newline : markdown.length).replace(/\r$/, '');
48
+ let fenceLine = line;
49
+ // CommonMark permits fences inside blockquote and list containers. Strip
50
+ // only the structural prefix used to introduce a fence; the recorded byte
51
+ // range still covers the untouched source.
52
+ for (;;) {
53
+ const quote = fenceLine.match(/^ {0,3}>[ \t]?/);
54
+ if (quote) {
55
+ fenceLine = fenceLine.slice(quote[0].length);
56
+ continue;
57
+ }
58
+ const list = fenceLine.match(/^ {0,3}(?:[-+*]|\d{1,9}[.)])[ \t]+/);
59
+ if (list) {
60
+ fenceLine = fenceLine.slice(list[0].length);
61
+ continue;
62
+ }
63
+ break;
64
+ }
65
+ if (!fence) {
66
+ const open = fenceLine.match(/^ {0,3}(`{3,}|~{3,})/);
67
+ if (open) fence = { char: open[1][0], length: open[1].length, start: lineStart };
68
+ } else {
69
+ const close = fenceLine.match(/^ {0,3}(`+|~+)[ \t]*$/);
70
+ if (close && close[1][0] === fence.char && close[1].length >= fence.length) {
71
+ fencedRanges.push({ start: fence.start, end: lineEnd });
72
+ fence = null;
73
+ }
74
+ }
75
+ lineStart = lineEnd;
76
+ }
77
+ if (fence) fencedRanges.push({ start: fence.start, end: markdown.length });
78
+
79
+ const spans = [];
80
+ for (let i = 0; i < markdown.length;) {
81
+ const fenced = fencedRanges.find((range) => i >= range.start && i < range.end);
82
+ if (fenced) {
83
+ i = fenced.end;
84
+ continue;
85
+ }
86
+ if (markdown[i] !== '`' || isEscaped(i)) {
87
+ i += 1;
88
+ continue;
89
+ }
90
+
91
+ let runLength = 1;
92
+ while (markdown[i + runLength] === '`') runLength += 1;
93
+ const lineStart = markdown.lastIndexOf('\n', i - 1) + 1;
94
+
95
+ const contentStart = i + runLength;
96
+ let close = contentStart;
97
+ while (close < markdown.length) {
98
+ if (markdown[close] !== '`' || isEscaped(close)) {
99
+ close += 1;
100
+ continue;
101
+ }
102
+ let closeLength = 1;
103
+ while (markdown[close + closeLength] === '`') closeLength += 1;
104
+ if (closeLength === runLength) break;
105
+ close += closeLength;
106
+ }
107
+
108
+ if (close >= markdown.length) break;
109
+ const lineEndIndex = markdown.indexOf('\n', close);
110
+ spans.push({
111
+ start: contentStart,
112
+ end: close,
113
+ value: markdown.slice(contentStart, close).trim(),
114
+ lineStart,
115
+ lineEnd: lineEndIndex >= 0 ? lineEndIndex : markdown.length,
116
+ });
117
+ i = close + runLength;
118
+ }
119
+
120
+ const target = spans.find((span) => candidateStart >= span.start && candidateEnd <= span.end);
121
+ if (!target || !MIGRATION_LEDGER_ACTION_VALUES.includes(target.value)) return false;
122
+
123
+ const referencedValues = new Set(
124
+ spans
125
+ .filter((span) => span.lineStart === target.lineStart && span.lineEnd === target.lineEnd)
126
+ .map((span) => span.value)
127
+ .filter((value) => MIGRATION_LEDGER_ACTION_VALUES.includes(value)),
128
+ );
129
+ return referencedValues.size >= 2;
130
+ }
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "$schema": "./builtin-manifest.schema.json",
3
3
  "schemaVersion": 1,
4
- "generatedAt": "2026-07-29T09:19:22.136Z",
5
- "instarVersion": "1.3.1048",
4
+ "generatedAt": "2026-07-29T10:16:28.309Z",
5
+ "instarVersion": "1.3.1049",
6
6
  "entryCount": 202,
7
7
  "entries": {
8
8
  "hook:session-start": {
@@ -2,5 +2,5 @@
2
2
  "sha256": "b75c147afd1f5a9843ca4eac372159f3623f24731fe63b2f59e48043ae488af9",
3
3
  "articleCount": 82,
4
4
  "generatedFrom": "docs/STANDARDS-REGISTRY.md",
5
- "packageVersion": "1.3.1048"
5
+ "packageVersion": "1.3.1049"
6
6
  }
@@ -0,0 +1,28 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: patch -->
5
+
6
+ ## What Changed
7
+
8
+ The development specification check now recognizes a reference list for a
9
+ shipped, closed telemetry enum instead of reading one member as postponed work.
10
+ Headings, callouts, fenced blocks, lone values, and standalone status words
11
+ remain checked.
12
+
13
+ ## What to Tell Your User
14
+
15
+ Technical state names in specifications no longer trigger an irrelevant
16
+ unfinished-work warning, while real scope decisions are still checked.
17
+
18
+ ## Summary of New Capabilities
19
+
20
+ - Closed-enum reference recognition in the development specification gate.
21
+
22
+ ## Evidence
23
+
24
+ - The live telemetry-enum regression now passes without an override.
25
+ - Real scope-decision forms and fenced examples remain blocked.
26
+ - The recognized value list is pinned to the shipped enum declaration.
27
+ - Removing the enum-list distinction makes the regression test fail.
28
+ - Focused tests and the repository typecheck pass.
@@ -0,0 +1,37 @@
1
+ # Keyword gates now distinguish an enum value from a prose decision
2
+
3
+ The development gate that checks technical specifications for unfinished work
4
+ used to read every occurrence of the word “deferred” as a decision to postpone
5
+ something. That is usually a useful warning, but it also caught a telemetry
6
+ value such as `deferred-in-flight`. The value names a state in software; it does
7
+ not say that implementation work is being postponed. Because the check blocks a
8
+ commit, the only escape was an audited override even though there was no work to
9
+ track.
10
+
11
+ This change adds one deliberately narrow distinction. It knows the actual
12
+ closed list of migration telemetry outcomes shipped by the code. A match is
13
+ treated as an enum reference only when the complete inline-code value belongs
14
+ to that list and at least one other member of the same closed list appears in
15
+ inline code on the same line. A lone `deferred-in-flight` still triggers the
16
+ gate because it could be an authorial status. The exact same words in ordinary
17
+ prose also trigger it, as do headings, blockquotes, callouts, indented list
18
+ text, fenced blocks, standalone `deferred`, unknown identifiers, and escaped
19
+ backticks. Those places can all carry genuine scope decisions, so the
20
+ implementation does not infer intent from Markdown or hyphen count.
21
+
22
+ The new parser preserves the existing tracker lookup, diagnostics, override,
23
+ and block behavior. It supports matching single- or multi-backtick inline-code
24
+ spans, refuses fenced blocks and malformed ranges, and has a parity test that
25
+ pins its local closed set to the shipped type declaration. Tests prove both
26
+ sides: the telemetry enum list passes, while real scope-decision forms remain
27
+ blocked. A mutation test removed the new distinction and the enum regression
28
+ failed immediately.
29
+
30
+ The same investigation also records the broader failure class in the defect
31
+ registry: a literal keyword is given authority without enough context to know
32
+ what it means. That class remains unconfirmed and open because the other named
33
+ systems do not share one safe mechanical fix. The outbound convergence check is
34
+ separately tracked for removal from blocking authority; the recall change is
35
+ owned elsewhere; and raw shell-input safety needs enforcement at the relay
36
+ boundary, not another text carve-out. This PR therefore fixes the live enum
37
+ false positive without pretending it closes those different problems.
@@ -0,0 +1,157 @@
1
+ # Side-Effects Review — Keyword-gate authorial context
2
+
3
+ **Version / slug:** `keyword-gate-authorial-context`
4
+ **Date:** `2026-07-29`
5
+ **Author:** `instar-codey`
6
+ **Second-pass reviewer:** `Euler`
7
+
8
+ ## Summary of the change
9
+
10
+ The instar-dev orphan-deferral blocker now excludes only a reference list for
11
+ the shipped MigrationPerEntryAction closed enum. The matched inline-code value
12
+ must belong to that enum and share a line with another enum member. It does not
13
+ remove headings, quotations, callouts, indented text, fenced content, lone enum
14
+ values, unknown identifiers, or standalone inline-code words from inspection.
15
+ A new pure helper owns the parse, and refusal-first tests cover the live enum
16
+ regression plus genuine decision shapes. The broader failure class is recorded
17
+ as an unconfirmed registry entry. ACT-1519 owns its confirmation/refinement;
18
+ ACT-1520 owns enforcement at the relay boundary.
19
+
20
+ ## Decision-point inventory
21
+
22
+ - `findOrphanDeferrals` — modified — skips one structurally qualified artifact
23
+ reference before applying the unchanged negation/tracker/block policy.
24
+ - `isKnownInlineCodeEnumReference` — added — validates equal-backtick
25
+ inline-code spans against the real closed enum and requires a same-line
26
+ sibling member; it has no authority outside the existing caller.
27
+ - Orphan-deferral commit block — pass-through — patterns, nearby-tracker
28
+ requirement, override, diagnostics, and exit behavior are unchanged.
29
+ - Defect-class registry — modified — names the broader cross-gate class as
30
+ unconfirmed; it grants no runtime authority.
31
+
32
+ ## 1. Over-block
33
+
34
+ Enum values shown alone, values rendered outside inline code, and unknown
35
+ identifier values still reach the existing blocker. This is intentional
36
+ conservatism: a lone `deferred-in-flight` may itself be an authorial
37
+ disposition. Historical quotations and fenced examples also still require a
38
+ tracker or the existing audited override.
39
+
40
+ The reported heading `## §8 — Out of scope (deliberate)` already passes current
41
+ main because none of the configured phrases matches it. A test pins that fact;
42
+ this change does not claim a heading fix that the current source cannot
43
+ reproduce.
44
+
45
+ ## 2. Under-block
46
+
47
+ An author could place a genuine decision inside a line that also enumerates
48
+ multiple real migration outcomes. That is the remaining narrow ambiguity.
49
+ Lone enum values, unknown multi-segment identifiers, standalone
50
+ `` `deferred` ``, headings, blockquotes/callouts, indented prose, fenced blocks,
51
+ escaped backticks, and the same enum token in prose all remain blocked and are
52
+ refusal-tested.
53
+
54
+ The broader keyword-authority class is not closed here. ACT-1519 already tracks
55
+ the Signal-vs-Authority correction and class refinement. ACT-1520 is the
56
+ tracked enforcement gap: move outbound checks to the relay/send boundary, where
57
+ quoting, variables, aliases, and wrappers do not decide what gets inspected.
58
+
59
+ ## 3. Level-of-abstraction fit
60
+
61
+ The helper answers a structured question at the structured boundary: “is this
62
+ match one member of the shipped closed enum being listed beside another
63
+ member?” It does not infer meaning from identifier shape or decide whether a
64
+ whole heading, quotation, code block, or paragraph is authorial. Two broader
65
+ implementations attempted those shortcuts; the required independent review
66
+ rejected them, and both designs were removed completely.
67
+
68
+ The other named gates are not forced through this helper. ACT-1519 owns moving
69
+ the outbound convergence regex out of blocking authority; recall has a
70
+ semantic-index design owned elsewhere; dangerous shell input needs
71
+ command-boundary enforcement.
72
+
73
+ ## 4. Signal vs authority compliance
74
+
75
+ **Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
76
+
77
+ This change adds no new blocking authority and does not promote a new keyword.
78
+ It narrows the evidence entering an existing blocker by validating an actual
79
+ closed enum reference. The existing blocker still uses literal language with commit authority,
80
+ so the broader constitutional concern is recorded honestly rather than called
81
+ closed: `brittle-keyword-authority`, unconfirmed, with `closure: gap` tied to
82
+ ACT-1520. ACT-1519 separately owns confirmation/refinement of the class.
83
+
84
+ ## 4b. Judgment-point check
85
+
86
+ No new static heuristic chooses among competing live signals. The helper
87
+ validates already-structured input against the shipped closed enum, with a
88
+ source-parity test. It cannot turn a non-match into a block; it can only remove
89
+ the demonstrated enum-list false positive from an existing candidate list.
90
+
91
+ ## 5. Interactions
92
+
93
+ - **Shadowing:** The identifier check runs before existing negation and nearby
94
+ tracker checks only for that candidate. All other candidates follow the
95
+ byte-identical path.
96
+ - **Double-fire:** None. The helper returns one boolean to the existing single
97
+ scan.
98
+ - **Races:** None. Parsing is pure and local to one staged document.
99
+ - **Feedback loops:** Fewer invalid blocks should reduce override use. The
100
+ override log and decision audit are otherwise unchanged.
101
+
102
+ ## 6. External surfaces
103
+
104
+ Instar contributors can commit specs that reference the closed telemetry enum
105
+ as a list without an audited override. Real unfinished-work language still receives the
106
+ same blocking diagnostic. No APIs, user messages, persistent runtime state,
107
+ external services, timing assumptions, or operator-facing actions change.
108
+
109
+ ## 6b. Operator-surface quality
110
+
111
+ No operator surface — not applicable.
112
+
113
+ ## 7. Multi-machine posture
114
+
115
+ Git-replicated source behavior. Every machine running the same source revision
116
+ gets the same pure classification; no machine-local state is added. The change
117
+ emits no user notice, holds no durable state, and generates no URLs.
118
+
119
+ ## 8. Rollback cost
120
+
121
+ Pure code and registry rollback. Reverting the helper import and exclusion
122
+ restores the previous over-block immediately. No data migration or agent-state
123
+ repair is required.
124
+
125
+ ## Conclusion
126
+
127
+ Clear to ship after the independent re-review. Two overly broad syntax
128
+ heuristics were rejected and removed; the final change binds only to the real
129
+ shipped enum, proves the nearby under-block boundaries, and records the larger
130
+ class without claiming to have solved unrelated gates.
131
+
132
+ ## Second-pass review
133
+
134
+ **Reviewer:** Euler
135
+ **Independent read of the artifact: approved after three blocking passes.**
136
+ The first two designs exempted broad Markdown/identifier shapes and were
137
+ removed. The final pass verified closed-enum parity, lone/prose/status refusal,
138
+ and top-level, blockquoted, and list-nested fenced ranges. It also verified that
139
+ ACT-1519 owns class refinement and ACT-1520 owns relay-boundary enforcement.
140
+ There are no remaining blocking findings.
141
+
142
+ ## Evidence pointers
143
+
144
+ - `tests/unit/instar-dev-precommit-deferrals.test.ts`
145
+ - `tests/unit/markdown-code-identifier.test.ts`
146
+ - `tests/unit/class-closure-registry.test.ts`
147
+ - Mutation proof: removing the identifier exclusion makes the enum test fail.
148
+ - `npx tsc --noEmit`
149
+ - `git diff --check`
150
+
151
+ ## Class-Closure Declaration (display-only mirror)
152
+
153
+ `defectClass: brittle-keyword-authority`, `closure: gap`, `gapItem: ACT-1520`.
154
+ The class is new and unconfirmed; the current PR closes the reproduced enum
155
+ instance but does not claim that a local lexical exclusion ends the broader
156
+ raw-input and natural-language authority class. ACT-1519 owns class
157
+ confirmation/refinement; ACT-1520 owns the missing relay-boundary enforcement.