instar 1.3.19 → 1.3.20

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.
@@ -0,0 +1,39 @@
1
+ /**
2
+ * reopen.ts — TS port of the auto-reopen-on-regression decision.
3
+ *
4
+ * Ports the decision embedded in cmd_apply_clusters (the-portal/.claude/scripts/
5
+ * feedback-processor.py, the regression branch ~:1543) out of the DB-write code
6
+ * into a pure function. When the clustering driver (cluster.ts) merges a new
7
+ * report into a cluster that was already fixed/resolved/deferred (a "possible
8
+ * regression" note), the cluster is auto-reopened. This computes the reopen
9
+ * outcome from the cluster's prior status:
10
+ *
11
+ * - deferred → AGED-REOPEN → status 'new', annotate actionTaken, no recurrence bump
12
+ * - otherwise → REGRESSION → status 'investigating', annotate researchNotes, bump recurrenceCount
13
+ *
14
+ * The DB writes (the prisma update with `{ increment: 1 }` etc.) stay in the
15
+ * adapter; this is the pure decision + the audit-note text. `now` is injected.
16
+ * Reference is interleaved with DB I/O, so equivalence is by faithful
17
+ * transcription + exhaustive unit tests (no clean isolated reference function to
18
+ * run a cross-runtime harness against).
19
+ */
20
+ import type { Cluster } from './types.js';
21
+ export interface ReopenDecision {
22
+ /** New lifecycle status to set on the reopened cluster. */
23
+ newStatus: 'new' | 'investigating';
24
+ /** Whether to bump recurrenceCount (chronic-regression accounting; NOT for aged-reopen). */
25
+ bumpRecurrence: boolean;
26
+ /** Which cluster field the audit note is appended to. */
27
+ annotateField: 'actionTaken' | 'researchNotes';
28
+ /** The note tag. */
29
+ noteTag: 'AGED-REOPEN' | 'REGRESSION';
30
+ /** The audit note appended to the chosen field. */
31
+ note: string;
32
+ }
33
+ /**
34
+ * Compute the auto-reopen outcome for a cluster being merged into on a regression.
35
+ * `wasStatus` is the cluster's status before reopen; `feedbackId` is the incoming
36
+ * report; `now` is the injected ISO timestamp (reference uses new Date().toISOString()).
37
+ */
38
+ export declare function computeReopen(cluster: Cluster, feedbackId: string, now: string): ReopenDecision;
39
+ //# sourceMappingURL=reopen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reopen.d.ts","sourceRoot":"","sources":["../../../src/feedback-factory/processor/reopen.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,WAAW,cAAc;IAC7B,2DAA2D;IAC3D,SAAS,EAAE,KAAK,GAAG,eAAe,CAAC;IACnC,4FAA4F;IAC5F,cAAc,EAAE,OAAO,CAAC;IACxB,yDAAyD;IACzD,aAAa,EAAE,aAAa,GAAG,eAAe,CAAC;IAC/C,oBAAoB;IACpB,OAAO,EAAE,aAAa,GAAG,YAAY,CAAC;IACtC,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,cAAc,CAiB/F"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * reopen.ts — TS port of the auto-reopen-on-regression decision.
3
+ *
4
+ * Ports the decision embedded in cmd_apply_clusters (the-portal/.claude/scripts/
5
+ * feedback-processor.py, the regression branch ~:1543) out of the DB-write code
6
+ * into a pure function. When the clustering driver (cluster.ts) merges a new
7
+ * report into a cluster that was already fixed/resolved/deferred (a "possible
8
+ * regression" note), the cluster is auto-reopened. This computes the reopen
9
+ * outcome from the cluster's prior status:
10
+ *
11
+ * - deferred → AGED-REOPEN → status 'new', annotate actionTaken, no recurrence bump
12
+ * - otherwise → REGRESSION → status 'investigating', annotate researchNotes, bump recurrenceCount
13
+ *
14
+ * The DB writes (the prisma update with `{ increment: 1 }` etc.) stay in the
15
+ * adapter; this is the pure decision + the audit-note text. `now` is injected.
16
+ * Reference is interleaved with DB I/O, so equivalence is by faithful
17
+ * transcription + exhaustive unit tests (no clean isolated reference function to
18
+ * run a cross-runtime harness against).
19
+ */
20
+ /**
21
+ * Compute the auto-reopen outcome for a cluster being merged into on a regression.
22
+ * `wasStatus` is the cluster's status before reopen; `feedbackId` is the incoming
23
+ * report; `now` is the injected ISO timestamp (reference uses new Date().toISOString()).
24
+ */
25
+ export function computeReopen(cluster, feedbackId, now) {
26
+ const wasStatus = cluster.status ?? null;
27
+ const isAged = wasStatus === 'deferred';
28
+ const newStatus = isAged ? 'new' : 'investigating';
29
+ const noteTag = isAged ? 'AGED-REOPEN' : 'REGRESSION';
30
+ const fixedInVersion = cluster.fixedInVersion || 'n/a';
31
+ // Verbatim from the reference's regressionNote template.
32
+ const note = `[${noteTag} ${now}] New report matched cluster previously marked '${wasStatus}' (fixedInVersion=${fixedInVersion}). Auto-reopened to '${newStatus}' for review. Report: ${feedbackId}`;
33
+ return {
34
+ newStatus,
35
+ bumpRecurrence: !isAged,
36
+ annotateField: isAged ? 'actionTaken' : 'researchNotes',
37
+ noteTag,
38
+ note,
39
+ };
40
+ }
41
+ //# sourceMappingURL=reopen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reopen.js","sourceRoot":"","sources":["../../../src/feedback-factory/processor/reopen.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAiBH;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,OAAgB,EAAE,UAAkB,EAAE,GAAW;IAC7E,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC;IACzC,MAAM,MAAM,GAAG,SAAS,KAAK,UAAU,CAAC;IACxC,MAAM,SAAS,GAA4B,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,eAAe,CAAC;IAC5E,MAAM,OAAO,GAAiC,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,YAAY,CAAC;IACpF,MAAM,cAAc,GAAI,OAAO,CAAC,cAAyB,IAAI,KAAK,CAAC;IAEnE,yDAAyD;IACzD,MAAM,IAAI,GAAG,IAAI,OAAO,IAAI,GAAG,mDAAmD,SAAS,qBAAqB,cAAc,wBAAwB,SAAS,yBAAyB,UAAU,EAAE,CAAC;IAErM,OAAO;QACL,SAAS;QACT,cAAc,EAAE,CAAC,MAAM;QACvB,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,eAAe;QACvD,OAAO;QACP,IAAI;KACL,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "instar",
3
- "version": "1.3.19",
3
+ "version": "1.3.20",
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-27T07:34:02.465Z",
5
- "instarVersion": "1.3.19",
4
+ "generatedAt": "2026-05-27T07:58:06.900Z",
5
+ "instarVersion": "1.3.20",
6
6
  "entryCount": 192,
7
7
  "entries": {
8
8
  "hook:session-start": {
@@ -0,0 +1,23 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- bump: patch -->
4
+
5
+ ## What Changed
6
+
7
+ Eighth increment of the **Feedback Factory Migration** (Dawn → Echo; spec `docs/specs/feedback-factory-migration.md`, approved). Ports the **auto-reopen-on-regression decision** from the reference Python (`cmd_apply_clusters` in `the-portal/.claude/scripts/feedback-processor.py`) into a pure function at `src/feedback-factory/processor/reopen.ts`.
8
+
9
+ When a new report gets grouped onto a bug that was already marked fixed, resolved, or deferred, the bug is automatically reopened for review. This computes how: a long-deferred bug becomes "new" again (an aged-reopen, logged on its action trail); a fixed/resolved bug becomes "investigating" again and bumps its recurrence counter (a regression, logged on its research notes). It also writes the exact audit note. Pure function; **not wired into any route or job yet** — no behavioral change.
10
+
11
+ ## What to Tell Your User
12
+
13
+ - The safety behavior that catches a bug "coming back from the dead" — a report landing on an already-fixed bug auto-reopens it instead of silently swallowing it — is now ported, including the audit note that records why it reopened.
14
+
15
+ ## Summary of New Capabilities
16
+
17
+ | Capability | How to Use |
18
+ |-----------|-----------|
19
+ | Auto-reopen decision (TS port) | Internal module `src/feedback-factory/processor/reopen.ts` — not yet wired |
20
+
21
+ ## Evidence
22
+
23
+ - The decision is interleaved with database writes in the reference, so equivalence is by faithful transcription plus both-sides-of-boundary unit tests (5): the deferred (aged-reopen) branch vs the fixed/resolved (regression) branch — each asserting the right new status, which field gets annotated, and whether the recurrence counter bumps — plus the audit-note string asserted verbatim and the `fixedInVersion=n/a` fallback.
@@ -0,0 +1,31 @@
1
+ # Side-Effects Review — auto-reopen-on-regression decision (Phase 1, increment 8)
2
+
3
+ **Slug:** `feedback-factory-reopen`
4
+ **Date:** `2026-05-27`
5
+ **Author:** Echo (autonomous)
6
+ **Spec:** `docs/specs/feedback-factory-migration.md` (converged v2, approved by Justin 2026-05-26)
7
+ **Scope:** The pure auto-reopen DECISION (which status/field/recurrence-bump + audit note) extracted from the regression branch of `cmd_apply_clusters`. The prisma writes stay in the (later) store adapter.
8
+
9
+ ## Summary of the change
10
+
11
+ Ports the auto-reopen-on-regression decision into `src/feedback-factory/processor/reopen.ts` as the pure `computeReopen(cluster, feedbackId, now)`. When the clustering driver merges a report into a fixed/resolved/deferred cluster (a "possible regression"), the cluster is auto-reopened: `deferred → AGED-REOPEN → status 'new', annotate actionTaken, no recurrence bump`; otherwise `REGRESSION → status 'investigating', annotate researchNotes, bump recurrenceCount`. Also templates the audit note verbatim. `now` injected. **Not wired into any route/job yet.**
12
+
13
+ ## Equivalence verification
14
+
15
+ The decision is interleaved with DB writes in the reference, so equivalence is by faithful transcription + both-sides-of-boundary unit tests (5): deferred vs fixed vs resolved → correct status/field/tag/recurrence; the audit-note string asserted verbatim (tag, time, prior status, `fixedInVersion`, new status, report id); `fixedInVersion=n/a` fallback.
16
+
17
+ ## Seven-dimension review
18
+
19
+ 1. **Over/under-reach** — Pure function, no I/O, no state, not imported by any runtime path. Returns the decision + note; the caller (store adapter) does the prisma update.
20
+ 2. **Level-of-abstraction fit** — Processor-logic layer, alongside cluster/transition/verify. The DB write (`{ increment: 1 }`, field append) is correctly left to the adapter.
21
+ 3. **Signal vs Authority** — N/A; produces a decision. The reopen is itself a legitimate guard (regression must not stay marked fixed) that exists in the reference.
22
+ 4. **Interactions** — None. New isolated module; nothing imports it yet. Pairs conceptually with `cluster.ts` (which emits the regression merge-note) but no code coupling yet.
23
+ 5. **Rollback cost** — Trivial: delete the module + tests.
24
+ 6. **Migration parity** — N/A. New internal library code; no agent-installed file touched.
25
+ 7. **Failure modes** — (a) Wrong field/status/recurrence per prior-status → both-sides tests. (b) Audit-note drift → asserted verbatim. (c) `now` non-determinism → injected.
26
+
27
+ ## Tests
28
+
29
+ - Tier-1 unit (CI): `tests/unit/feedback-factory/reopen.test.ts` — 5 tests (aged vs regression branches, resolved, verbatim note, n/a fallback).
30
+ - No cross-runtime parity harness (decision interleaved with DB writes in the reference; equivalence by transcription + boundary tests).
31
+ - No integration/E2E this increment: not wired; attaches when the apply/store layer lands. Reasoned, documented.