instar 0.28.83 → 0.28.84

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 (83) hide show
  1. package/dashboard/index.html +239 -0
  2. package/dist/cli.js +10 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/memoryBackfillEvidence.d.ts +69 -0
  5. package/dist/commands/memoryBackfillEvidence.d.ts.map +1 -0
  6. package/dist/commands/memoryBackfillEvidence.js +220 -0
  7. package/dist/commands/memoryBackfillEvidence.js.map +1 -0
  8. package/dist/commands/server.d.ts.map +1 -1
  9. package/dist/commands/server.js +72 -1
  10. package/dist/commands/server.js.map +1 -1
  11. package/dist/core/EvolutionManager.d.ts +73 -0
  12. package/dist/core/EvolutionManager.d.ts.map +1 -1
  13. package/dist/core/EvolutionManager.js +376 -0
  14. package/dist/core/EvolutionManager.js.map +1 -1
  15. package/dist/core/SharedStateLedger.d.ts.map +1 -1
  16. package/dist/core/SharedStateLedger.js +4 -0
  17. package/dist/core/SharedStateLedger.js.map +1 -1
  18. package/dist/core/types.d.ts +90 -1
  19. package/dist/core/types.d.ts.map +1 -1
  20. package/dist/core/types.js +8 -0
  21. package/dist/core/types.js.map +1 -1
  22. package/dist/memory/EvidenceRenderer.d.ts +64 -0
  23. package/dist/memory/EvidenceRenderer.d.ts.map +1 -0
  24. package/dist/memory/EvidenceRenderer.js +119 -0
  25. package/dist/memory/EvidenceRenderer.js.map +1 -0
  26. package/dist/memory/SemanticMemory.d.ts +61 -1
  27. package/dist/memory/SemanticMemory.d.ts.map +1 -1
  28. package/dist/memory/SemanticMemory.js +381 -11
  29. package/dist/memory/SemanticMemory.js.map +1 -1
  30. package/dist/server/AgentServer.d.ts +4 -0
  31. package/dist/server/AgentServer.d.ts.map +1 -1
  32. package/dist/server/AgentServer.js +2 -0
  33. package/dist/server/AgentServer.js.map +1 -1
  34. package/dist/server/routes.d.ts +8 -0
  35. package/dist/server/routes.d.ts.map +1 -1
  36. package/dist/server/routes.js +369 -0
  37. package/dist/server/routes.js.map +1 -1
  38. package/dist/tasks/DivergenceChecker.d.ts +89 -0
  39. package/dist/tasks/DivergenceChecker.d.ts.map +1 -0
  40. package/dist/tasks/DivergenceChecker.js +255 -0
  41. package/dist/tasks/DivergenceChecker.js.map +1 -0
  42. package/dist/tasks/LruCache.d.ts +33 -0
  43. package/dist/tasks/LruCache.d.ts.map +1 -0
  44. package/dist/tasks/LruCache.js +88 -0
  45. package/dist/tasks/LruCache.js.map +1 -0
  46. package/dist/tasks/RateLimiter.d.ts +61 -0
  47. package/dist/tasks/RateLimiter.d.ts.map +1 -0
  48. package/dist/tasks/RateLimiter.js +108 -0
  49. package/dist/tasks/RateLimiter.js.map +1 -0
  50. package/dist/tasks/TaskFlowDueWaker.d.ts +29 -0
  51. package/dist/tasks/TaskFlowDueWaker.d.ts.map +1 -0
  52. package/dist/tasks/TaskFlowDueWaker.js +73 -0
  53. package/dist/tasks/TaskFlowDueWaker.js.map +1 -0
  54. package/dist/tasks/TaskFlowMaintenanceSweeper.d.ts +40 -0
  55. package/dist/tasks/TaskFlowMaintenanceSweeper.d.ts.map +1 -0
  56. package/dist/tasks/TaskFlowMaintenanceSweeper.js +131 -0
  57. package/dist/tasks/TaskFlowMaintenanceSweeper.js.map +1 -0
  58. package/dist/tasks/TaskFlowRegistry.d.ts +180 -0
  59. package/dist/tasks/TaskFlowRegistry.d.ts.map +1 -0
  60. package/dist/tasks/TaskFlowRegistry.js +791 -0
  61. package/dist/tasks/TaskFlowRegistry.js.map +1 -0
  62. package/dist/tasks/ThreadlineFlowBridge.d.ts +54 -0
  63. package/dist/tasks/ThreadlineFlowBridge.d.ts.map +1 -0
  64. package/dist/tasks/ThreadlineFlowBridge.js +129 -0
  65. package/dist/tasks/ThreadlineFlowBridge.js.map +1 -0
  66. package/dist/tasks/task-flow-registry.store.sqlite.d.ts +77 -0
  67. package/dist/tasks/task-flow-registry.store.sqlite.d.ts.map +1 -0
  68. package/dist/tasks/task-flow-registry.store.sqlite.js +350 -0
  69. package/dist/tasks/task-flow-registry.store.sqlite.js.map +1 -0
  70. package/dist/tasks/task-flow-types.d.ts +229 -0
  71. package/dist/tasks/task-flow-types.d.ts.map +1 -0
  72. package/dist/tasks/task-flow-types.js +128 -0
  73. package/dist/tasks/task-flow-types.js.map +1 -0
  74. package/package.json +1 -1
  75. package/src/data/builtin-manifest.json +78 -78
  76. package/upgrades/0.28.84.md +89 -0
  77. package/upgrades/side-effects/taskflow-phase1.md +130 -0
  78. package/upgrades/side-effects/taskflow-phase2.md +110 -0
  79. package/upgrades/side-effects/taskflow-phase3a.md +138 -0
  80. package/upgrades/side-effects/taskflow-phase5.md +234 -0
  81. package/upgrades/side-effects/wikiclaim-evidence-phase1.md +138 -0
  82. package/upgrades/side-effects/wikiclaim-evidence-phase4.md +129 -0
  83. package/upgrades/side-effects/wikiclaim-evidence-phase5.md +285 -0
@@ -0,0 +1,285 @@
1
+ # Side-Effects Review — WikiClaim Evidence Phase 5 (backfill CLI + render hardening)
2
+
3
+ **Version / slug:** `wikiclaim-evidence-phase5`
4
+ **Date:** 2026-05-10
5
+ **Author:** Echo
6
+ **Second-pass reviewer:** required (idempotency + producer-narrowing-respected + cross-product privacy)
7
+
8
+ ## Summary of the change
9
+
10
+ Ships the final WikiClaim phase per spec § Migration Plan line 347:
11
+
12
+ 1. `instar memory backfill-evidence [--dry-run]` — one-shot, idempotent
13
+ CLI that walks every existing `MemoryEntity`, pattern-matches the legacy
14
+ `source: string` field, and synthesizes a single `MemoryEvidence` row
15
+ of `kind: 'external-url'` when (and only when) the source string is an
16
+ anchored `https?://…` URL. Any non-URL source string is left alone —
17
+ `evidence: []` per spec § Risks line 357 ("no LLM in the migration path").
18
+ 2. `src/memory/EvidenceRenderer.ts` — single privacy-enforcement helper
19
+ exposing `renderEvidenceForScope(entity, viewerScope)`. Per spec
20
+ § Storage and Privacy line 315 the renderer is THE enforcement boundary;
21
+ this lands the helper now (before Phase 4 HTTP/dashboard rendering
22
+ touches evidence in user-facing output) so every downstream consumer
23
+ has exactly one place to filter from. `SemanticMemory`'s own read paths
24
+ are switched to delegate to the helper for the entity-visible /
25
+ evidence-visible predicates — keeping one source of truth.
26
+
27
+ ### Phase 5 scope deliberately narrowed vs spec § Migration line 208–212
28
+
29
+ The spec lists four legacy-source patterns:
30
+
31
+ | Pattern | Backfilled to | Phase 5 status |
32
+ |---|---|---|
33
+ | `https?://…` | `kind: 'external-url'` | **shipped** |
34
+ | `session:ABC` | `kind: 'session'` | **skipped** |
35
+ | `user:Justin` | `kind: 'message'` | **skipped** |
36
+ | `observation` / any other | `evidence: []` | unchanged (no write) |
37
+
38
+ The narrowing is structural, not a deferral. Per spec § Producers line 229
39
+ and the Phase 1 `PRODUCER_KIND_ALLOWLIST`, the `manual` producer (the only
40
+ producer this CLI can invoke from outside any of the in-process subsystems)
41
+ is allowed to write `external-url` ONLY. The `session` and `message` kinds
42
+ require the `DecisionJournal` and `LearnSkill` producers respectively, which
43
+ have access to the originating subsystem's context (session metadata,
44
+ conversation transcript) that the CLI does not. **We deliberately do NOT
45
+ widen the allowlist to make migration easier** — that would unwind the
46
+ producer-kind capability boundary the spec installs.
47
+
48
+ A future bridge that walks legacy `session:` and `user:` sources from
49
+ inside DecisionJournal / LearnSkill (with full producer context) is a
50
+ clean follow-up and explicitly tracked in MEMORY.md.
51
+
52
+ What lands:
53
+
54
+ - `src/commands/memoryBackfillEvidence.ts` — pattern-match + dup-check +
55
+ `addEvidence('manual')` call.
56
+ - `src/cli.ts` — register `memory backfill-evidence` subcommand with
57
+ `--dry-run` flag and `-d <dir>`.
58
+ - `src/memory/EvidenceRenderer.ts` — `renderEvidenceForScope`,
59
+ `filterEvidenceArrayForScope`, `isEntityVisibleAtScope`,
60
+ `isEvidenceVisibleAtScope`. The latter two are imported by
61
+ `SemanticMemory.ts` so the read-path predicates are no longer locally
62
+ defined — they delegate to the renderer.
63
+ - `tests/unit/memory-backfill-evidence.test.ts` — 17 vitest cases:
64
+ URL pattern match, non-URL skip, producer narrowing respected,
65
+ idempotency across two runs, idempotency across entity privacy tiers,
66
+ dry-run is non-mutating, apply-after-dry-run still writes, privacy
67
+ inherits across every entity scope.
68
+ - `tests/unit/evidence-render-privacy.test.ts` — cross-product table:
69
+ 3 entity scopes × 5 evidence tiers × 3 viewer scopes (45 combinations)
70
+ plus six edge-case assertions. Spec § Risks line 356 ("render every
71
+ privacyScope × privacyTier combination and assert no leak") satisfied.
72
+ - `upgrades/side-effects/wikiclaim-evidence-phase5.md` (this file).
73
+
74
+ ## Decision-point inventory
75
+
76
+ - URL anchoring (`^https?:\/\/\S+$`) — **add** — hard-invariant pattern
77
+ match at the migration entry. Not judgment. Anchoring (no embedded URLs
78
+ inside other text) keeps the migration deterministic across re-runs as
79
+ the matcher evolves.
80
+ - Idempotency dup-check (`existing.some(ev.kind === 'external-url' &&
81
+ (ev.path === source || ev.sourceId === source))`) — **add** —
82
+ equality-based. Not judgment.
83
+ - Dup-check viewer-scope (`'private'` default, configurable) — **add** —
84
+ reads the widest scope so the dup-check sees every existing row. A
85
+ narrower default would silently allow a duplicate write against a
86
+ private-tier evidence row on a shared-project entity. Tests pin this.
87
+ - Producer narrowing (`addEvidence(..., 'manual')` only) — **enforced**
88
+ by `PRODUCER_KIND_ALLOWLIST`; the CLI inherits that gate, does not
89
+ re-implement it.
90
+ - `privacyTier: undefined` on synthesized rows — **add** — per spec
91
+ § Risks line 360, never auto-upgrade.
92
+ - `confidence: 0.5` on synthesized rows — **add** — matches spec
93
+ § Migration line 210's suggested low-confidence value for coarse
94
+ legacy provenance.
95
+ - `updatedAt: entity.createdAt` — **add** — preserves temporal ordering
96
+ and means a second run on the same entity produces identical content.
97
+ - `EvidenceRenderer` helper — **add** — single-enforcement render path;
98
+ no ad-hoc render exists today (Phase 4 HTTP/dashboard hasn't shipped)
99
+ so this is preventive. `SemanticMemory`'s existing read-path
100
+ predicates are switched to delegate to the helper so we have ONE
101
+ visibility-comparison map across the codebase.
102
+
103
+ ---
104
+
105
+ ## 1. Over-block
106
+
107
+ **URL anchoring rejects embedded URLs:** `source: "see https://example.com"`
108
+ is skipped, not backfilled. By design — extracting a partial URL creates
109
+ ambiguity ("which one of the URLs in this string is the real source?")
110
+ and re-runs could backfill different URLs as the extractor evolves.
111
+ Producers that need to retroactively cite an embedded URL can run a
112
+ follow-up migration with a more permissive extractor; we keep the v1
113
+ backfill conservative.
114
+
115
+ **Whitespace not trimmed:** `source: " https://x.com "` is skipped.
116
+ Same reason — trim semantics depend on convention; v1 keeps the rule
117
+ "the source IS the URL, not a string containing a URL."
118
+
119
+ **Producer-narrowing rejects `session:` / `user:`:** Already covered
120
+ above. These need their own producer bridges, not this CLI. Explicitly
121
+ tracked.
122
+
123
+ ## 2. Under-block
124
+
125
+ - **`external-url` is not URL-validated:** Beyond the `https?://\S+`
126
+ anchor we don't parse the URL. A malformed-but-anchored value like
127
+ `https://[invalid:` would be backfilled. The renderer treats
128
+ `external-url.path` as display-only per spec § Threat Model line 372
129
+ ("renderers MUST treat `path` for `external-url` as display-only —
130
+ never auto-fetch"), so an invalid URL is a display-time annoyance,
131
+ not an SSRF or injection vector.
132
+ - **`note` cap not retroactively applied:** We set a fixed
133
+ `'Backfilled from legacy MemoryEntity.source (Phase 5 migration)'`
134
+ note (52 bytes, well under the 500-byte cap). No risk.
135
+ - **Concurrency:** The CLI doesn't take a DB lock. If a producer is
136
+ actively writing while backfill runs, both will succeed; the dup-check
137
+ loses the race for entities that get a fresh `external-url` evidence
138
+ row from a producer mid-scan. Mitigation: dup-check on every entity
139
+ before write (already present); on race, the producer's row lands
140
+ first and ours is skipped on second run. Operationally the CLI is
141
+ intended for offline / quiet-period invocation; this is documented.
142
+
143
+ ## 3. Level-of-abstraction fit
144
+
145
+ Right layer. The backfill belongs at the CLI / command layer because:
146
+ - It uses public `SemanticMemory` APIs (`export()`, `getEvidence()`,
147
+ `addEvidence()`) — no private-state access.
148
+ - It's a one-shot operator-invoked migration, not a runtime path.
149
+ - Pattern matching is at the edge (the CLI), not inside storage.
150
+
151
+ `EvidenceRenderer` belongs in `src/memory/` because it owns evidence-shape
152
+ filtering logic; pulling it out of `SemanticMemory.ts` (without dragging
153
+ better-sqlite3 with it) lets non-SQLite render contexts (HTTP shapers,
154
+ dashboard JSON producers) use it without spurious dependencies.
155
+
156
+ ## 4. Signal vs authority compliance
157
+
158
+ **Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
159
+
160
+ - [x] **No** — this change has no judgment-level block/allow surface.
161
+
162
+ The backfill's "skip" outcomes are mechanic-level pattern misses
163
+ (`URL_SOURCE_PATTERN.test(source) === false`) or idempotency dedupes
164
+ (equality-based dup-check). The renderer's filtering is mechanic-level
165
+ ordering comparison (`tier ordinal >= evidence tier ordinal`). No
166
+ intelligent gate, no judgment surface.
167
+
168
+ The actual semantic question — "should this entity be cited by an
169
+ external URL?" — was already answered by whoever set `source` on the
170
+ entity. The CLI replays that answer into typed evidence; it does not
171
+ re-decide.
172
+
173
+ ## 5. Interactions
174
+
175
+ - **Phase 2 producers landing in parallel:** EvolutionManager /
176
+ DispatchExecutor producers write `feedback`, `pattern-entity`,
177
+ `job-run`, `ledger-entry`, `supersedes-evidence` rows. Backfill only
178
+ writes `external-url`. Zero overlap; dup-check is keyed on
179
+ `(kind === 'external-url' && path === source)` so even if Phase 2 had
180
+ attached an `external-url` row via a different producer (none of them
181
+ are allowed to per the allowlist), the URL-equality dup-check still
182
+ catches it.
183
+ - **Phase 3 DecisionJournal / LearnSkill:** Same story — different
184
+ kinds; non-overlapping dup-check keys.
185
+ - **`SemanticMemory.getEvidence` / `findCitations` / `getEntityWithEvidence`**:
186
+ Now delegate to the `EvidenceRenderer.isEntityVisibleAtScope` and
187
+ `isEvidenceVisibleAtScope` exports for the entity-visible /
188
+ evidence-visible predicates. The Phase 1 in-file copies are removed.
189
+ Verified by re-running the full Phase 1 test suite
190
+ (`semantic-memory-evidence.test.ts` 21/21, `semantic-memory.test.ts`
191
+ 49/49, `semantic-memory-privacy.test.ts` 32/32) — all green.
192
+ - **JSONL append log:** Every `addEvidence` call in the backfill emits
193
+ the existing `addEvidence` JSONL action; replay path is unchanged
194
+ (Phase 1's deferred-handler note about JSONL replay still applies —
195
+ unaffected by Phase 5).
196
+ - **No HTTP / dashboard / threadline render today:** Phase 4 hasn't
197
+ landed; there is no ad-hoc evidence renderer in current production
198
+ code to replace. The helper is preventive — landing it now means
199
+ Phase 4 has exactly one place to call into when it adds HTTP routes
200
+ and dashboard panels. **No ad-hoc paths were found and replaced.**
201
+ This is documented as the intent rather than presented as completed
202
+ retro-replacement work.
203
+
204
+ ## 6. External surfaces
205
+
206
+ - **Other agents on the same machine**: None. Backfill is per-agent,
207
+ per-state-directory.
208
+ - **Other users of the install base**: A new subcommand appears on
209
+ `instar memory --help`. Default behavior of `instar memory <other>`
210
+ is unchanged. Running the CLI is opt-in.
211
+ - **External systems**: None. Backfill is local-only; the
212
+ `external-url` rows it writes store the URL as a string for display,
213
+ never fetched (per spec § Threat Model line 372).
214
+ - **Persistent state**: One `addEvidence` JSONL row per backfilled
215
+ entity, one `entity_evidence` table row per backfilled entity.
216
+ Bounded by the number of entities with URL sources.
217
+ - **Privacy posture**: Tighter — backfilled rows inherit entity scope
218
+ (`privacyTier: undefined`); never auto-upgrade. The renderer helper
219
+ centralizes filtering; even if a Phase 4 callsite forgets to filter,
220
+ the helper's existence + spec-mandated call pattern catches the bug
221
+ at code-review time.
222
+
223
+ ## 7. Rollback cost
224
+
225
+ - **Hot-fix release**: Pure additive change. `git revert <merge-commit>`
226
+ ships as the next patch.
227
+ - Backfilled `entity_evidence` rows from the `manual` producer would
228
+ remain in the DB; they are well-formed and harmless (renderer hides
229
+ them per viewer scope, never auto-fetched). If cleanup is desired,
230
+ `DELETE FROM entity_evidence WHERE kind = 'external-url'
231
+ AND note = 'Backfilled from legacy MemoryEntity.source (Phase 5 migration)'`
232
+ is a precise rollback query.
233
+ - `EvidenceRenderer.ts` deletion is fine; `SemanticMemory` would need
234
+ to re-introduce the local predicates. The revert PR can re-add them.
235
+ - **Data migration**: None. Backfill is one-shot per entity by design;
236
+ rollback doesn't undo the writes (they're treated as legitimate
237
+ evidence rows), and re-running after revert+restore would just
238
+ produce zero writes thanks to idempotency.
239
+ - **Agent state repair**: None.
240
+ - **User visibility**: Zero today (no HTTP / dashboard renderers Phase 4
241
+ hasn't shipped); minimal after Phase 4 lands (filtered evidence rows
242
+ appear next to entities).
243
+
244
+ ---
245
+
246
+ ## Conclusion
247
+
248
+ WikiClaim Phase 5 ships an idempotent, dry-run-safe, URL-only backfill
249
+ CLI plus the renderer helper that closes the privacy-enforcement loop the
250
+ spec § Storage and Privacy line 315 calls for. The CLI's intentional
251
+ narrowness (URLs only, never `session:` / `user:`) preserves the
252
+ `PRODUCER_KIND_ALLOWLIST` boundary Phase 1 installed; widening for
253
+ migration convenience would unwind a structural defense. The renderer
254
+ helper is preventive — Phase 4 HTTP/dashboard hasn't landed yet, so
255
+ there are zero ad-hoc renderers to replace today, but the helper is in
256
+ place and `SemanticMemory`'s own read paths now delegate to it so the
257
+ codebase has exactly one visibility-comparison map. Cleared to ship
258
+ pending second-pass concurrence.
259
+
260
+ ---
261
+
262
+ ## Second-pass review
263
+
264
+ _To be filled in by independent reviewer subagent._
265
+
266
+ ---
267
+
268
+ ## Evidence pointers
269
+
270
+ - New tests:
271
+ `npx vitest run tests/unit/memory-backfill-evidence.test.ts tests/unit/evidence-render-privacy.test.ts`
272
+ → 34/34 passing (~80ms).
273
+ - Regression:
274
+ `npx vitest run tests/unit/semantic-memory-evidence.test.ts tests/unit/semantic-memory.test.ts tests/unit/semantic-memory-privacy.test.ts`
275
+ → 102/102 passing.
276
+ - Typecheck: `npx tsc --noEmit` → clean.
277
+ - Cross-product privacy coverage:
278
+ `tests/unit/evidence-render-privacy.test.ts` — 3 entity scopes × 5
279
+ evidence tiers × 3 viewer scopes (45 combinations) + edge-case
280
+ assertions.
281
+ - Spec source of truth:
282
+ `docs/specs/OPENCLAW-IMPORT-WIKICLAIM-EVIDENCE-SPEC.md` §§ Migration
283
+ of Existing MemoryEntity Records (line 202), Risks lines 357, 360,
284
+ Migration Plan Phase 5 (line 347), Storage and Privacy line 315.
285
+ - Phase 1 artifact: `upgrades/side-effects/wikiclaim-evidence-phase1.md`.