instar 1.3.288 → 1.3.290

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.
Files changed (39) hide show
  1. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  2. package/dist/core/PostUpdateMigrator.js +17 -0
  3. package/dist/core/PostUpdateMigrator.js.map +1 -1
  4. package/dist/feedback-factory/cutoverReadiness.d.ts +45 -0
  5. package/dist/feedback-factory/cutoverReadiness.d.ts.map +1 -1
  6. package/dist/feedback-factory/cutoverReadiness.js +51 -0
  7. package/dist/feedback-factory/cutoverReadiness.js.map +1 -1
  8. package/dist/feedback-factory/dryrun/HttpParitySource.d.ts +14 -0
  9. package/dist/feedback-factory/dryrun/HttpParitySource.d.ts.map +1 -1
  10. package/dist/feedback-factory/dryrun/HttpParitySource.js +67 -4
  11. package/dist/feedback-factory/dryrun/HttpParitySource.js.map +1 -1
  12. package/dist/feedback-factory/migration/importRunner.d.ts +117 -0
  13. package/dist/feedback-factory/migration/importRunner.d.ts.map +1 -0
  14. package/dist/feedback-factory/migration/importRunner.js +162 -0
  15. package/dist/feedback-factory/migration/importRunner.js.map +1 -0
  16. package/dist/scaffold/templates.d.ts.map +1 -1
  17. package/dist/scaffold/templates.js +1 -0
  18. package/dist/scaffold/templates.js.map +1 -1
  19. package/dist/server/AgentServer.d.ts.map +1 -1
  20. package/dist/server/AgentServer.js +25 -0
  21. package/dist/server/AgentServer.js.map +1 -1
  22. package/dist/server/CapabilityIndex.d.ts.map +1 -1
  23. package/dist/server/CapabilityIndex.js +3 -1
  24. package/dist/server/CapabilityIndex.js.map +1 -1
  25. package/dist/server/middleware.d.ts.map +1 -1
  26. package/dist/server/middleware.js +3 -0
  27. package/dist/server/middleware.js.map +1 -1
  28. package/dist/server/routes.d.ts.map +1 -1
  29. package/dist/server/routes.js +35 -0
  30. package/dist/server/routes.js.map +1 -1
  31. package/package.json +1 -1
  32. package/scripts/instar-dev-precommit.js +31 -10
  33. package/src/data/builtin-manifest.json +64 -64
  34. package/src/scaffold/templates.ts +1 -0
  35. package/upgrades/1.3.289.md +50 -0
  36. package/upgrades/1.3.290.md +21 -0
  37. package/upgrades/decisions-per-entry.eli16.md +5 -0
  38. package/upgrades/side-effects/decisions-per-entry.md +44 -0
  39. package/upgrades/side-effects/import-runner.md +66 -0
@@ -0,0 +1,50 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: patch -->
5
+
6
+ ## What Changed
7
+
8
+ The migration readiness checker gained the piece that makes its data-integrity
9
+ condition achievable: an end-to-end import runner, plus a safe "rehearsal" mode.
10
+ Until now the readiness surface could only WAIT for an import integrity report
11
+ that nothing could produce. Agents can now trigger a server-side rehearsal that
12
+ fetches the real live data, imports it into a throwaway in-memory copy exactly
13
+ as the real migration would, and verifies every row survived bit-for-bit —
14
+ without writing anything durable. The rehearsal's verdict is visible in the
15
+ readiness status, clearly separated from the real thing: only the REAL import
16
+ (still credentials-gated) can ever satisfy the readiness condition.
17
+
18
+ Also closed a small logging gap found live: a timed-out page download that
19
+ aborted while reading the response body now produces the same clear "page N
20
+ timed out" failure as one that aborted while connecting.
21
+
22
+ ## What to Tell Your User
23
+
24
+ If your agent is driving a data migration, it can now prove the import pipeline
25
+ works against today's real data — a full rehearsal with zero risk — before
26
+ anyone flips anything. The readiness status shows the rehearsal result
27
+ separately from the real import, so "ready" still means exactly what it meant.
28
+
29
+ ## Summary of New Capabilities
30
+
31
+ - `POST /cutover-readiness/import-dryrun` — trigger a server-side import
32
+ rehearsal (live fetch → in-memory AS-IS import → per-row integrity gate);
33
+ zero durable data writes; never greens the canonical integrity condition.
34
+ - `GET /cutover-readiness/import-dryrun` — the last rehearsal's verdict.
35
+ - `GET /cutover-readiness` now includes an informational `importDryRun` leg.
36
+ - Maturity: stable for the rehearsal path; the REAL import awaits the
37
+ credentials-gated database adapter (it reuses this same runner).
38
+
39
+ ## Evidence
40
+
41
+ The runner's verification is observation-based: the integrity gate runs over
42
+ what the target READS BACK, not what was sent — unit tests prove a target that
43
+ silently mangles, drops, or invents rows is caught (checksum-differs /
44
+ missing-in-target / extra-in-target respectively). The readiness-honesty rule is
45
+ structural, not conventional: the constructor refuses wiring the rehearsal
46
+ report onto the canonical integrity path, and a passing rehearsal leaves
47
+ `ready: false` with the canonical report absent (asserted at unit, integration,
48
+ and E2E tiers — 35 new tests, all green). The body-read classification gap was
49
+ reproduced from a live failure log (2026-06-05 11:01Z: raw "operation was
50
+ aborted" with no page context) and is covered by a dedicated unit test.
@@ -0,0 +1,21 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: patch -->
5
+
6
+ ## What Changed
7
+
8
+ `writeDecisionAudit` in `scripts/instar-dev-precommit.js` writes one file per decision instead of appending a line to one shared JSONL. Two PRs each ADDING a distinct path can never merge-conflict; appending to the same file's tail always did. Same payload, same best-effort/never-block semantics, collision-suffixed filenames.
9
+
10
+ ## What to Tell Your User
11
+
12
+ Nothing user-visible — this is contributor infrastructure. Pull requests no longer fail to merge over the development decision-audit log.
13
+
14
+ ## Summary of New Capabilities
15
+
16
+ - Each gated commit's decision-audit record is now its own file under `.instar/instar-dev-decisions/<timestamp>-<slug>.json` (chronological by filename), staged so it still rides the commit it describes.
17
+ - The legacy `.instar/instar-dev-decisions.jsonl` is frozen history — no new appends.
18
+
19
+ ## Evidence
20
+
21
+ Live failure this fixes (2026-06-05): PR #824 passed all 19 CI checks, then `gh pr merge --squash --admin` failed with "Pull Request has merge conflicts" — `git merge` against main showed exactly ONE conflicted file, `.instar/instar-dev-decisions.jsonl`, because sibling PRs had appended their own audit lines to the same tail while #824 was in CI. Unblocked manually by union-resolving; this change removes the class. Pinned by `tests/unit/instar-dev-precommit-audit-staging.test.ts`: the gate-blocked commit still stages its entry file (the #814 property preserved), two evaluations produce two DISTINCT paths (the conflict-immunity property), and the frozen legacy JSONL is not appended to; the deferrals suite's audit-shape test re-pinned to the per-entry record (riskFloor number, belowFloor, suggestedTier, reasons array). 16/16 tests green.
@@ -0,0 +1,5 @@
1
+ # Parallel PRs stop colliding on the decision-audit log
2
+
3
+ Every gated commit records a small audit note (what tier was declared, what the risk classifier suggested). A recent fix made that note ride along inside the commit itself — which solved one problem (notes were evaporating with temporary build folders) but quietly created another: all the notes went into ONE shared file, each commit appending a line at the end. Git can't merge two different "last lines" of the same file, so whenever two pull requests were in flight at the same time — which is now the normal state with three agents shipping in parallel — the second one to merge hit a conflict on that file. This actually happened within hours: a PR passed every check and then failed to merge over nothing but the audit log.
4
+
5
+ The fix: each decision now gets its own tiny file (named by timestamp and change name) inside a decisions folder, instead of a line appended to a shared file. Two PRs each ADDING a different file never conflict — git and GitHub merge that trivially. Nothing about the audit content changes, the note still rides the commit it describes, and the old log file stays in place as frozen history. The chronological order you used to get from reading the file top-to-bottom now comes from sorting filenames, which start with the timestamp.
@@ -0,0 +1,44 @@
1
+ # Side-Effects Review — per-entry decision-audit files (task #80)
2
+
3
+ **Version / slug:** `decisions-per-entry`
4
+ **Date:** `2026-06-05`
5
+ **Author:** `echo`
6
+ **Second-pass reviewer:** `self-review under the Tier-1 lite lane; the audit-continuity question (does the trail survive the format change?) addressed below`
7
+
8
+ ## Summary of the change
9
+
10
+ `writeDecisionAudit` in the pre-commit gate writes each decision as its own file `.instar/instar-dev-decisions/<ts>-<slug>.json` (staged immediately, preserving #814's ride-the-commit property) instead of appending one line to the shared `.instar/instar-dev-decisions.jsonl`. Distinct paths per PR cannot merge-conflict — including GitHub's server-side merge, which does not honor custom merge drivers. The legacy JSONL freezes in place as history.
11
+
12
+ ## Decision-point inventory
13
+
14
+ - `writeDecisionAudit` — modified — per-entry file write + stage; same payload fields (ts/slug/tiers/riskFloor/reasons/belowFloor/files/loc); collision-suffix counter for same-ms-same-slug; returns the entry path (used by the belowFloor console message).
15
+ - `DECISIONS_LOG` const — removed (legacy path noted in comment); `DECISIONS_DIR` added.
16
+ - Tests — `instar-dev-precommit-audit-staging.test.ts` re-pinned to the per-entry contract + a NEW conflict-immunity test (two evaluations → two distinct paths) + asserts the legacy JSONL is NOT created; `instar-dev-precommit-deferrals.test.ts` audit-shape test re-pinned.
17
+
18
+ ## 1. Direction-of-failure analysis
19
+
20
+ - **Old failure (live, PR #824):** CI-green PR fails admin-merge on the audit file tail — recurring at parallel-PR cadence, blocks every second merge, requires manual union resolution each time.
21
+ - **New worst case:** the writer remains best-effort (try/catch, never blocks the gate) — an audit I/O failure loses ONE entry, exactly as before. Filename collision (same ms + same slug) is suffix-countered, pinned by test.
22
+ - **Audit continuity:** the legacy file is untouched history; new entries are chronologically sortable by filename (`ls` order = time order). Readers: only tests read the trail today (grep-verified); both updated.
23
+ - **In-flight PRs written under the old scheme:** once main's shared file stops growing, their single appended line vs main's unchanged tail merges CLEANLY — landing this fix un-jams the conflict class for already-open PRs too (the conflict needed BOTH sides appending).
24
+
25
+ ## 2. Over-permit
26
+
27
+ None — the gate's blocking logic is untouched; only where the audit record lands.
28
+
29
+ ## 3. Scope deliberately NOT taken
30
+
31
+ - No migration of legacy JSONL lines into per-entry files — history stays where it was written; a reader that wants the full trail reads both (documented in the script comment).
32
+ - No `.gitattributes merge=union` belt for the legacy file — GitHub's server-side merge ignores it, and with the file frozen the local-rebase benefit is moot.
33
+
34
+ ## 4. Migration parity
35
+
36
+ None needed — the gate script lives in the repo (`scripts/`), not in agent-installed files; every checkout gets it with the commit. `.instar/instar-dev-decisions/` is created on demand by the writer.
37
+
38
+ ## 5. Token/cost impact
39
+
40
+ None — same write volume, one file create vs one append per gated commit.
41
+
42
+ ## 6. Rollback
43
+
44
+ Revert the commit; the writer returns to appending the shared JSONL (and the conflict class returns with it).
@@ -0,0 +1,66 @@
1
+ # Side-effects review — feedback import runner + dry-run rehearsal route
2
+
3
+ The cutover-readiness checker (G2.4) composes two conditions; one of them —
4
+ `integrity-gate-pass` — reads a persisted import IntegrityReport that NOTHING in
5
+ the codebase could produce: the integrity-gate core shipped as pure functions
6
+ (#778) with no end-to-end runner wired to live data. This builds the runner and a
7
+ zero-durable-writes REHEARSAL route, so the import pipeline is provable on real
8
+ production data today and the real import is one adapter away when the
9
+ creds-gated cloud DB (G1.4) lands.
10
+
11
+ ## 1. The change
12
+
13
+ - `migration/importRunner.ts` (new): `runImport(source, target)` — pre-import
14
+ fingerprint-uniqueness scan (aborts BEFORE any write on a collision),
15
+ parent-before-child AS-IS import through the new `ImportTarget` seam, then the
16
+ full integrity gate over what the target READS BACK (intent is never trusted
17
+ over observation). `InMemoryImportTarget` (deep-copy isolation, duplicate-PK
18
+ refusal) is the dry-run/test implementation; the real Prisma adapter is a thin
19
+ future shim over the same seam. Status-equivalence checks CLUSTER statuses only
20
+ (feedback rows carry their own processing-state domain).
21
+ - `HttpParitySource`: opt-in `captureRaw` keeps cluster + feedback rows VERBATIM
22
+ for the import read (parity mode unchanged); plus a live-found classification
23
+ gap closed — an abort during the page BODY read now maps to the same classified
24
+ 504 naming the page/budgets (was: raw "operation was aborted", observed live
25
+ 2026-06-05 11:01Z).
26
+ - `CutoverReadiness`: `runImportDryRunPass()` persists the rehearsal envelope to
27
+ a SEPARATE `feedback-import-dryrun.json` path; `importDryRunStatus()` surfaces
28
+ it as `importDryRun` in `status()`. **Readiness honesty is structural**: the
29
+ constructor REFUSES wiring the dry-run path onto the canonical integrity path,
30
+ and `ready` composes integrity + parity only — a green rehearsal can never
31
+ green the gate.
32
+ - Routes: `POST /cutover-readiness/import-dryrun` (server computes, agent only
33
+ triggers — T7; same always-logged-outcome contract and same 360s per-path
34
+ timeout as parity-pass) + `GET /cutover-readiness/import-dryrun` (read-only).
35
+ - Awareness: CapabilityIndex, site reference/api.md, CLAUDE.md template + an
36
+ idempotent PostUpdateMigrator splice for agents already carrying the Cutover
37
+ Readiness section (Migration Parity Standard).
38
+
39
+ ## 2. Blast radius
40
+
41
+ Additive. No existing route's behavior changes; `GET /cutover-readiness` gains
42
+ the informational `importDryRun` field. The rehearsal writes ONE new state file
43
+ (`state/feedback-import-dryrun.json`) and nothing else durable. The mandate
44
+ conditions (`integrity-gate-pass`, `parity-zero-divergence`) are untouched — the
45
+ rehearsal cannot reach either. No config migration needed (no new config keys;
46
+ the runner reuses `feedbackMigration.paritySource`). The real import stays
47
+ creds-gated and unbuilt at the adapter layer by design.
48
+
49
+ ## 3. Test coverage
50
+
51
+ - Unit (18 new, import-runner.test.ts): AS-IS preservation incl. unknown fields,
52
+ collision abort writes NOTHING, mangling/dropping/inventing targets each caught
53
+ by the readback gate, dangling-FK, unknown-status divergence, full v1 legacy
54
+ vocabulary accepted, adapter-supplied schema honored, sequence planning,
55
+ duplicate-PK refusal, deep-copy isolation, snake_case ids.
56
+ - Unit (6 new, http-parity-source.test.ts): raw capture verbatim, cross-page
57
+ accumulation + dedup, raw reads refuse without captureRaw/prepare, body-read
58
+ abort → classified 504, non-abort body parse failure propagates.
59
+ - Unit (6 new, cutover-readiness.test.ts): dry-run records to the separate path
60
+ and `ready` stays false; failed check records nothing; no-source refusal;
61
+ pre-import abort surfaced; the same-path wiring REFUSED; torn envelope reads
62
+ never-ran.
63
+ - Integration (4 new): POST rehearsal over the full HTTP pipeline with a hostile
64
+ body contributing nothing; GET verdict; 409-records-nothing; 503 when absent.
65
+ - E2E (1 new): import-dryrun routes ALIVE on the production init path
66
+ (Bearer-gated, 409-not-404 without a source, composed status carries the leg).