instar 1.3.16 → 1.3.17

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.
@@ -1 +1 @@
1
- {"version":3,"file":"MentorStageBForensics.d.ts","sourceRoot":"","sources":["../../src/scheduler/MentorStageBForensics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAKL,KAAK,eAAe,EACrB,MAAM,uCAAuC,CAAC;AAU/C;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAiB9E;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,eAAe,EAAE,CAgCvF;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,mFAAmF;IACnF,OAAO,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAC/C;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAS/F"}
1
+ {"version":3,"file":"MentorStageBForensics.d.ts","sourceRoot":"","sources":["../../src/scheduler/MentorStageBForensics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAKL,KAAK,eAAe,EACrB,MAAM,uCAAuC,CAAC;AA6B/C;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CA0B9E;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,eAAe,EAAE,CAgCvF;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,mFAAmF;IACnF,OAAO,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAC/C;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAS/F"}
@@ -14,10 +14,28 @@
14
14
  import { ISSUE_BUCKETS, ISSUE_SEVERITIES, } from '../monitoring/FrameworkIssueLedger.js';
15
15
  const MAX_FINDINGS_PER_RUN = 10; // bound a single tick's output
16
16
  const MAX_TITLE = 200;
17
- /** A normalized slug for a conservative dedupKey when the model omits one. */
17
+ /** A normalized slug for a dedupKey from a model-supplied stable id (keeps it as-is, kebabed). */
18
18
  function slug(s) {
19
19
  return s.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 80) || 'untitled';
20
20
  }
21
+ /**
22
+ * Derive a conservative dedupKey from a title when the model omits one. Strips
23
+ * VOLATILE tokens that would split one issue across runs — standalone numbers,
24
+ * timeout/percent/version literals, and hex-ish ids — keeping only the stable
25
+ * symptom words. (§13.3: titles are operator-dependent; this is the last-resort
26
+ * fallback — the prompt asks the model for a stable id directly.)
27
+ */
28
+ function deriveStableSlug(title) {
29
+ const stable = title
30
+ .toLowerCase()
31
+ .replace(/\bv?\d+(?:\.\d+)+\b/g, ' ') // version strings (v1.3.14, 1.2.3)
32
+ .replace(/\b\d+\s*(?:ms|s|m|h|%|k|kb|mb|tokens?|turns?)\b/g, ' ') // 8s, 42%, 15k, 1 turn
33
+ .replace(/\b[0-9a-f]{6,}\b/g, ' ') // hex ids / shas
34
+ .replace(/\b\d+\b/g, ' ') // any remaining standalone numbers
35
+ .replace(/\s+/g, ' ')
36
+ .trim();
37
+ return slug(stable || title);
38
+ }
21
39
  /**
22
40
  * Build the Stage-B forensic prompt. The model is asked to classify ONLY what
23
41
  * the signals actually evidence into the three buckets, and to output a strict
@@ -36,6 +54,15 @@ export function buildForensicPrompt(framework, signals) {
36
54
  ``,
37
55
  `Output ONLY a JSON array (no markdown, no prose). Each element:`,
38
56
  ` {"bucket": "...", "title": "<short>", "severity": "low|medium|high", "dedupKey": "<stable-id>"}`,
57
+ ``,
58
+ `CRITICAL — the dedupKey must be STABLE across runs. It is a short lowercase-kebab identifier`,
59
+ `for the ROOT SYMPTOM, NOT a rephrasing of your title. Use the SAME id you would use if you saw`,
60
+ `this exact issue again next time. Base it on the symptom class + the component, e.g.`,
61
+ `"feedback-webhook-429", "inputguard-review-timeout", "codex-single-turn-exit". Do NOT put`,
62
+ `version numbers, timestamps, session ids, counts, or wording variations in the dedupKey —`,
63
+ `those drift and would split one issue into many. Two reports of the same root problem MUST`,
64
+ `produce the same dedupKey.`,
65
+ ``,
39
66
  `If the signals evidence no concrete issue, output []. Never invent issues.`,
40
67
  ``,
41
68
  `--- Signals ---`,
@@ -84,7 +111,7 @@ export function parseForensicFindings(raw, framework) {
84
111
  : 'medium';
85
112
  const dedupKey = typeof o.dedupKey === 'string' && o.dedupKey.trim()
86
113
  ? `${framework}::${slug(o.dedupKey)}`
87
- : `${framework}::${slug(title)}`;
114
+ : `${framework}::${deriveStableSlug(title)}`;
88
115
  out.push({ bucket: bucket, title, severity, dedupKey, signature: title });
89
116
  }
90
117
  return out;
@@ -1 +1 @@
1
- {"version":3,"file":"MentorStageBForensics.js","sourceRoot":"","sources":["../../src/scheduler/MentorStageBForensics.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"MentorStageBForensics.js","sourceRoot":"","sources":["../../src/scheduler/MentorStageBForensics.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "instar",
3
- "version": "1.3.16",
3
+ "version": "1.3.17",
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-05-27T06:41:15.968Z",
5
- "instarVersion": "1.3.16",
4
+ "generatedAt": "2026-05-27T06:57:14.226Z",
5
+ "instarVersion": "1.3.17",
6
6
  "entryCount": 192,
7
7
  "entries": {
8
8
  "hook:session-start": {
@@ -0,0 +1,34 @@
1
+ # Instar Upgrade Guide — NEXT
2
+
3
+ <!-- bump: patch -->
4
+
5
+ ## What Changed
6
+
7
+ **Framework-Onboarding Mentor System — forensic dedup stability.** A live validation run surfaced
8
+ that the same root issue could be logged 2–3 times across ticks under different IDs, because when the
9
+ model omitted a stable identifier the system derived one from the (drifting) wording — the exact
10
+ title-dependence the design doc warns against. Fixed two ways: the forensic prompt now demands a
11
+ stable, symptom-based identifier (no version numbers, counts, ids, or wording variants), and the
12
+ fallback derivation strips volatile tokens before building a key. Live re-run confirmed cross-tick
13
+ merging now works (16 → 12 issues over the same 3 iterations). Still dormant.
14
+
15
+ ## What to Tell Your User
16
+
17
+ - The mentor's notebook now keeps one entry per real problem even when the wording wobbles between
18
+ inspections — no more slow drizzle of near-duplicate entries.
19
+
20
+ ## Summary of New Capabilities
21
+
22
+ | Capability | How to Use |
23
+ |-----------|-----------|
24
+ | Stable forensic dedup | Automatic — the same root issue collapses to one ledger entry across ticks |
25
+
26
+ ## Evidence
27
+
28
+ Found by running the real loop through multiple iterations against real data (the iterate-and-harden
29
+ loop working as designed). Fix proven by: 3 new unit tests asserting the model-supplied stable key is
30
+ preferred, that two phrasings of one issue differing only in volatile tokens (`8s` vs `8000ms`)
31
+ collapse to the **same** dedupKey, and that version/percent/hex tokens are stripped from the derived
32
+ fallback; plus a live re-run on Echo's real server.log + Codey's real rollouts showing cross-tick
33
+ merge dropped duplicates from 16 → 12 over the same 3 iterations. 13 unit tests total; affected
34
+ push-config suite green vs canonical main.
@@ -0,0 +1,49 @@
1
+ # Side-Effects Review — Forensic dedupKey stability (§19.4 follow-on)
2
+
3
+ **Spec:** `docs/specs/FRAMEWORK-ONBOARDING-MENTOR-SPEC.md` (converged 5 iters, approved by Justin)
4
+ **Change:** Hardens Stage-B forensic dedupKey stability so the same root issue produces the same
5
+ key across ticks (§13.3: "title is too operator-dependent"). Found by **live validation**: running
6
+ the real forensics through 3 iterations on real data logged the same issue 2–3× under different
7
+ keys, because the LLM-omitted-key fallback derived from the (drifting) title. Fix: (1) the prompt
8
+ now demands a stable, symptom-based lowercase-kebab `dedupKey` with explicit "no versions / numbers /
9
+ ids / wording variants" guidance; (2) the fallback derivation strips volatile tokens
10
+ (numbers, version/percent/unit literals, hex ids) before slugging.
11
+ **Files:** `src/scheduler/MentorStageBForensics.ts`, `tests/unit/MentorStageBForensics.test.ts`,
12
+ `upgrades/NEXT.md`.
13
+
14
+ ## Principle check (Phase 1)
15
+
16
+ Decision point? No. This sharpens an identifier (dedup quality) on a signal-only path. No gating.
17
+
18
+ ## The seven questions
19
+
20
+ 1. **Over-block.** Over-aggressive token stripping could in theory merge two genuinely-distinct
21
+ issues whose titles differ only in numbers. Mitigated: the strip only applies to the *fallback*
22
+ (when the LLM omits a key); the LLM-supplied symptom key is preferred. And §13.3's design makes
23
+ false merges the conservative-acceptable direction only on `dedupKey` while `signature` (the full
24
+ title) preserves the distinction for probable-dup review.
25
+ 2. **Under-block.** LLM forensics are inherently variable run-to-run, so cross-tick merging is
26
+ improved (live-measured 16→12 issues over the same 3 iterations) but not perfect; the residual
27
+ is handled by the `signature`-based probable-dup review (§13.3), unchanged.
28
+ 3. **Level-of-abstraction fit.** Pure-module change (prompt + key derivation); no I/O. Correct layer.
29
+ 4. **Signal vs authority.** Unchanged — signal-only.
30
+ 5. **Interactions.** Only changes the `dedupKey` a finding carries; the ledger's existing
31
+ conservative auto-merge on `(framework, dedupKey)` does the rest (no ledger change).
32
+ 6. **External surfaces.** None — internal forensic logic.
33
+ 7. **Rollback cost.** Trivial — revert the prompt + derivation change.
34
+
35
+ ## Phase 5 — second-pass
36
+
37
+ Not required — a dedup-quality refinement on a pure, tested module; no decision/spawn/session surface.
38
+
39
+ ## Validation
40
+
41
+ Live re-run on Echo's real server.log + Codey's real rollouts: before, 3 iterations produced 16
42
+ issues (near-zero cross-tick merge); after, the same 3 iterations produced 12 (iterations 2–3 each
43
+ merged ~half their findings into existing issues) — the cross-tick merge now demonstrably works.
44
+
45
+ ## Testing
46
+
47
+ 13 unit tests (+3): prefers the model-supplied stable key; fallback strips volatile tokens so
48
+ phrasing/number variants of one issue collapse to the same key; version/percent/hex tokens stripped.
49
+ Affected push-config suite green vs canonical main.