ID-59 {59.1} RESEARCH — Per-UC write-back (UC1/4/6/3/5/8) + Diff-UI re-point + edit_intent storage shape
ID-59 {59.1} RESEARCH — Per-UC write-back + Diff-UI re-point + edit_intent storage shape
Section titled “ID-59 {59.1} RESEARCH — Per-UC write-back + Diff-UI re-point + edit_intent storage shape”Status: RESEARCH complete — recommendations PENDING Liam (§7 decision queue). Authored 08/06/2026, spec-chain START per ID-93 §6.2 (“more than minimal” → start the T9 chain so any schema slice ratifies pre-cutover) + §6.8 (edit_intent storage research run — Liam’s instinct is a sidecar
.md, wants a research run to be certain). RESEARCH-only — no implementation, no DDL, no code edits.Task: ID-59 (T9,
in_progress) — “Per-UC write-back (UC1/4/6/3/5/8) + Diff-UI sidecar re-point”. Largest of the T9–T14 family (3 PLAN units).Companion artefact: this dir’s
TECH.md(“Concurrent-Edit Intent Arbitration — TECH”,[CURRENT-CANONICAL], LANDED-S244 commit12a20963) is the arbitration rule spec (T-1..T-5). This RESEARCH does NOT supersede it — it extends the surface to per-UC write-back wiring, the Diff-UI re-point, and the storage-shape decision the TECH explicitly deferred (TECH §1 out-of-scope bullet 2; §4.2/§4.4 storage option scoping).
0. Headline corrections to the dispatch brief (verify-first discipline)
Section titled “0. Headline corrections to the dispatch brief (verify-first discipline)”Three load-bearing claims in the surrounding context are WRONG against the live surface and the spec chain must be authored on the corrected facts.
| Claim (as received) | Verified reality | Evidence |
|---|---|---|
| ”the concurrent-edit-intent-arbitration substrate LANDED S244 — reuse, do not re-invent” | The TECH spec landed S244 (commit 12a20963). The arbitration code does NOT exist. grep -rniE 'edit[_]?intent' lib/ app/ components/ types/ scripts/ supabase/ hooks/ contexts/ → zero hits; grep -rniE 'arbitrat' over the TS corpus → zero hits (08/06/2026). T9 is GREENFIELD implementation against a ratified rule, not a re-point onto landed code. | TECH.md T-1 “Current state: Greenfield … zero hits as of 20/05/2026” — re-confirmed 08/06/2026. |
edit_intent lands on content_history.edit_intent (+ actor_id array + arbitration_inputs jsonb) — TECH §4.2/§4.4 name these columns | None of those columns exist. content_history today = id, content_item_id, version, title, content, brief, detail, reference, metadata jsonb, change_summary, change_type, created_by, created_at, change_reason. No edit_intent, no actor_id (there is created_by uuid), no arbitration_inputs. TECH §4.2/§4.4 describe a target shape, not current state — and call it “the most likely choice”, NOT ratified. | supabase/migrations/20260416102457_pre_squash_reconciliation.sql:3485 (CREATE TABLE content_history). |
write-back lands on source_documents.original_path (PLAN §4.9 + TECH §1) | The prod column is storage_path (NOT NULL), not original_path. The pipeline writes the source-relative POSIX path into storage_path, and that same string is the uuid5 PK seed. There is no original_path column on source_documents. | SOURCE_DOCUMENTS_SCHEMA flow.py:1185; write site flow.py:1971 "storage_path": rel_path; PK seed flow.py:1809. |
Truth set used (per ID-93 §1.2 adversarial discipline): scripts/cocoindex_pipeline/flow.py
(the ACTIVE pipeline — NOT the retired scripts/kb_pipeline/; ID-46/T14 retires the latter), the
migration corpus under supabase/migrations/, the cocoindex write-model runbook
(themes/canonical-pipeline/reference/cocoindex-write-model.md, R1–R5), the v1-completion-sequence
ordering board, this dir’s TECH.md, and live empirical import checks (§6).
1. Method + code-intelligence orientation
Section titled “1. Method + code-intelligence orientation”1.1 gitnexus / ccc orientation
Section titled “1.1 gitnexus / ccc orientation”Per the “Always Do” code-intel block: edit_intent / arbitrate are GREENFIELD — there is no
indexed symbol to run gitnexus_context against (the function the TECH spec mandates,
arbitrate() / arbitrateMany(), does not yet exist). The orientation therefore reduces to an
adversarial grep sweep of the existing write-back-adjacent surface, which IS the correct
greenfield fallback:
- Editor substrate (EXISTS, deps installed): Tiptap
3.23.4family incl.@tiptap/extension-collaboration3.23.4,@tiptap/markdown3.23.4;yjs ^13.6.30;y-prosemirror ^1.3.7(package.json:81–92, 131–132). Editor components present:components/item-detail/content-editor.tsx,components/item-detail/inline-content-editor.tsx,components/item-detail/editor-toolbar.tsx,components/qa/qa-answer-display.tsx,components/procurement/response-editor.tsx; save-path helperslib/editor/save-safety.ts,lib/editor-utils.ts,lib/drawer-insert.ts. Correction to TECH §T-1: the TECH says “the Yjs collab plugin is not yet wired” — the dependency is installed (extension-collaborationyjs+y-prosemirror); what is absent is the wiring of a collab provider and theedit_intentcapture UX. State this precisely in PRODUCT/TECH.
- Write-back routes (EXIST, but no edit_intent):
app/api/items/[id]/route.ts,app/api/items/[id]/history/route.ts,app/api/items/[id]/history/[versionId]/route.ts,app/api/items/[id]/rollback/route.ts,app/api/source-documents/[id]/route.ts. These writecontent_historyrows today; none stamps anedit_intent(grep: zero hits). - Diff-UI substrate (EXISTS):
components/item-detail/version-history.tsx(content-item version diff),components/intelligence/prompt-refinement/prompt-diff-view.tsx(prompt diff — adjacent, not the target). The “source_document_diffssubstrate” the PLAN says to re-point FROM does NOT exist as a table in the migration corpus (grep: zero hits) — it was a planned substrate that was never built, so the “re-point” is really “build Diff-UI against the markdown-sidecar/version model for the first time”. Flag this to PRODUCT.
1.2 Coupling-class vocabulary (inherited from ID-93 §1.1)
Section titled “1.2 Coupling-class vocabulary (inherited from ID-93 §1.1)”C1 ingest-capture · C2 zero-row window · C3 id-coupled (renumbering / source-layout exposure) ·
C4 shape-only · C5 verified-decoupled. The edit_intent storage decision is the C3 item ID-93
§4 flagged; resolving its class is the core of §4 below.
2. Per-UC write-back path map
Section titled “2. Per-UC write-back path map”Per-UC scope is the ID-31 PLAN §4.9 in-scope list (the T9 source of truth). Each UC is mapped to
its write surface, whether it touches the cocoindex source-file layout, and its substrate entry
points. The arbitration function (TECH T-1..T-5) only sits in the UC1/UC4/UC6 path — the
Tiptap+Yjs concurrent-edit paths. UC3/UC5/UC8 do not produce CRDT-merge concurrency and so do not
invoke arbitrate().
| UC | What | Write surface | Touches cocoindex source-file layout? | Invokes arbitrate()? | Substrate entry point (to build) |
|---|---|---|---|---|---|
| UC1 typo fix | Tiptap+Yjs in-platform edit | content_items.content (DB) + the source file at source_documents.storage_path (Candidate A two-phase; sidecar .md for binary) | YES — writes the walked file; cocoindex observes on next POST /walk | YES | KH-server save endpoint → arbitrate(intents) → write file + DB; stamp merged edit_intent (storage = §4) |
| UC4 paragraph rewrite | Tiptap+Yjs + edit-intent gate at save | same as UC1 + citation re-anchor | YES | YES | same save endpoint as UC1; edit_intent captured at save time per 02-data-flow.md §8 |
| UC6 user-direct Q&A pair revision | Tiptap+Yjs, KH-DB-only (05-qa-flow.md §8/§9) | q_a_pairs + q_a_pair_history (NO file write — Q&A pairs are KH-DB-only in v1; sidecar materialisation DEFERRED-v1.1, PLAN §5 item 18) | NO (v1) | YES | KH-server Q&A save → arbitrate() → q_a_pair_history version row |
| UC6 AI-suggest | source-doc change → AI proposes → user commits (Candidate B) | q_a_pairs after user commit | NO (the trigger is a source-doc change cocoindex already detects; the write is DB) | NO (single-actor commit) | Anthropic API propose → review queue → commit; gated on the cocoindex source-binding trigger (T8 ✅) |
| UC3 sweeping rename | two variants: (A) KH-server find-replace iteration over affected files; (B) smart-agent Anthropic text-editor-tool, per-match approve | the source files at storage_path (variant A iterates them; variant B edits via tool) | YES — variant A/B both rewrite walked files | NO (sweep is a batched single-actor operation) | KH-server sweep orchestrator with a shared sweep-ID + per-record provenance; rollback per 06-… §6.0.6 — gated on Spike#3 (write-back adapter contract) |
| UC5 bid→Q&A promotion | bid/form response → q_a_pair draft with lineage | q_a_pairs (+ lineage to source response + question), KH-DB-only | NO | NO | review-queue promotion (UC5-adjacent); depends on T6 q_a_pairs schema (✅) + the {64.14} form rename for response context |
| UC8 cross-workspace dedup | KH-server orchestration + Claude API similarity reasoning (Candidate A) | q_a_pairs merge + q_a_pair_history merge-lineage | NO (DB-level merge) | NO | KH-server dedup orchestrator + Claude reasoning — gated on Spike#10 (UC8 dedup substrate) + UC8 ratification + bl-74 q_a_pair_history lineage columns |
Out of T9 scope (PLAN §4.9 scope-out, restated so the spec chain does not creep): UC7 + UC10
(external-folder change — handled natively by cocoindex source binding, T8 ✅); UC9 (scope-tag
taxonomy — separate OPS work-package); UC2 (collapsed into UC1, S228); UC8 Candidate C upgrade
(DEFERRED-v1.1); Yjs y-supabase persistence (DEFERRED-v1.1, PLAN §5 item 19).
2.1 The single shared write-back contract (Spike#3)
Section titled “2.1 The single shared write-back contract (Spike#3)”UC1/UC3/UC4 all rewrite walked source files at source_documents.storage_path. The cocoindex
write-model (R1, R4, §1) means the write-back is NOT a cocoindex concern — cocoindex only observes
the file on the next POST /walk (boot never walks — ID-83/bl-221). The write-back adapter is a
KH-server concern that must:
- Resolve the on-disk path under
COCOINDEX_SOURCE_PATHfromstorage_path(the source-relative POSIX string — flow.py_to_source_relative, write-model R4:file.file_path.pathis ABSOLUTE in prod, normalised source-relative forstorage_path). - Write the new bytes (preserving the path so the uuid5 PK is stable across the next walk — write-model
R1/§1: integrity is by
uuid5(_KH_PIPELINE_DOC_NS, "<kind>:"+rel_path)derivation, NOT FK; a path change would mint a NEW PK = a new content_item, orphaning the old). - Stamp the merged
edit_intent(UC1/UC4) so the next walk’s re-classification policy (02-data-flow.md§8.2) is honoured.
This adapter contract is Spike#3 (PENDING per PLAN §4.9 risk). It is a cross_doc_link, not a sibling dependency (§5). The write-model R1/R4 constraints ARE the empirical substrate Spike#3 must resolve against — much of Spike#3 is already answerable from the landed write-model runbook.
3. Diff-UI re-point plan
Section titled “3. Diff-UI re-point plan”What the PLAN ratified (S243 Item 5): Diff-UI is RETAINED for v1 (was DEFERRED-v1.1), re-pointed
from the source_document_diffs substrate to markdown sidecar revision comparison.
Verified reality:
source_document_diffsis not a table (grep over migrations: zero hits) — it was a planned substrate, never built. So “re-point FROMsource_document_diffs” is a misnomer: there is nothing to re-point off. The work is “build Diff-UI against the available revision model”.- The available revision model today is
content_history(version rows:version,content,created_at,created_by,change_type,change_summary) — already surfaced bycomponents/item-detail/version-history.tsxandapp/api/items/[id]/history/route.ts. - The “markdown sidecar revision comparison” framing presupposes a per-revision markdown artefact to
diff. For UC1/UC4 (file-backed content) the natural diff is old-file-bytes ↔ new-file-bytes (the
markdown the editor produced). For UC6 (KH-DB-only Q&A) the diff is
q_a_pair_historyold-content ↔ new-content. There is no separate “sidecar diff store” needed — the diff is computed on demand from the two revisions.
Recommended re-point plan (for PRODUCT/TECH to formalise):
- Diff-UI consumes the existing version model (
content_historyfor content items;q_a_pair_historyfor Q&A pairs) — NOT a newsource_document_diffssubstrate (which would be speculative DDL the OQ-64-5 “structurally complete, based on ratified specs” policy disallows). - Diff computation is client-side or a thin RPC over two revision blobs — no new storage.
- The “markdown sidecar” wording resolves to: for file-backed UCs the diffed artefact IS the markdown
the sidecar
.md/source file carries; this is a rendering decision, not a storage decision. It does NOT, by itself, require the §4 sidecar-.mdstorage shape foredit_intent.
This means Diff-UI does NOT gate the §4 storage decision — it works off whatever revision model
exists regardless of where edit_intent lives. Flag in PRODUCT so the two are not conflated.
4. edit_intent STORAGE shape — the PRIORITY research run (Liam, §6.8)
Section titled “4. edit_intent STORAGE shape — the PRIORITY research run (Liam, §6.8)”The question: where does the (post-arbitration) edit_intent label live? Three options from ID-93
§4 / phase-b-prerequisite-2b-cocoindex-operational.md §369 / TECH §4.2:
(a) a content_history column; (b) a sidecar .md metadata file (Liam’s instinct); (c) a
cocoindex flow arg.
4.1 What “source-file layout frozen at re-ingest” actually means
Section titled “4.1 What “source-file layout frozen at re-ingest” actually means”This is the crux of the sidecar-.md analysis, and it resolves cleanly against the live pipeline.
The cocoindex source-file layout = the set of files under COCOINDEX_SOURCE_PATH that
localfs.walk_dir(live=True, recursive=True) enumerates (flow.py header line 4; _coco_api.py
exposes localfs; app_main binds COCOINDEX_SOURCE_PATH flow.py:2877). For each walked file:
- The source-relative POSIX path becomes
source_documents.storage_path(flow.py:1971) and the uuid5 PK seed forcontent_items/source_documents/content_chunks/entity_mentions(write-model R1/§1; flow.py:1809). Path = identity. - A file that is not content but lands in the walked folder is ingested as content unless it is
explicitly skipped. The ONLY skip today is a hardcoded single-filename match for the workspace
manifest:
if file.file_path.path.name == _WORKSPACE_MANIFEST_FILENAME: return(flow.py:1667). There is no generic sidecar-suffix exclusion. .mdis a first-class content suffix (_NON_FORM_SUFFIXES = {".md", ".txt", ".html"}flow.py:1346;.md→text/markdownflow.py:1355; converts successfully viaconvert_binary_to_markdown). A.mdsidecar dropped next to a source file would therefore be walked and ingested as a spuriouscontent_item— exactly the BUG-B failure mode the manifest.jsonhit on the S297 live smoke (write-model §4 row B; flow.py:1664–1666 comment).
So “freezing the source-file layout” means: deciding, BEFORE the ID-45 full-corpus re-ingest,
the exact set of files cocoindex walks and how each is classified (content vs skip), because that set
mints the PKs the entire corpus is keyed on. A sidecar-.md storage shape would add a new file
class to the walked layout and therefore:
- require a new skip rule in
ingest_file(generalise the single-filename manifest skip to a sidecar-suffix/-naming convention) — a pipeline code change (C1-adjacent: it changes how the run classifies files), and - that rule MUST be in place before the re-ingest, or every sidecar
.mdbecomes a junkcontent_itemwith its own uuid5 PK in the handover corpus (un-cheap to unpick post-run — C3).
This is the coupling ID-93 §4 flagged. It is REAL and confirmed: the sidecar-.md option couples
to the re-ingest and would have to settle pre-cutover.
4.2 Option comparison (evidence-based)
Section titled “4.2 Option comparison (evidence-based)”| Dimension | (a) content_history column | (b) sidecar .md metadata | (c) cocoindex flow arg |
|---|---|---|---|
| Where it lives | New column(s) on content_history (DB) | Frontmatter/companion file in the walked corpus | Argument threaded through the cocoindex flow (e.g. via the run/manifest) |
| Couples to re-ingest? | Only via OQ-64-9 (content_history retention disposition, {64.7}). content_history is C3-id-coupled (1,225 prod rows reference content_item_id which renumbers) — BUT ID-93’s edit_intent is a NEW column, write-only post-cutover; it adds nothing to the renumber exposure beyond what {64.7} already plans. | YES, hard. Adds a file class to the frozen walked layout → needs a pre-run skip rule (§4.1) or junk content_items. Must settle pre-cutover. | YES, conceptually. The flow arg is set at walk time; the re-ingest run would need the arg plumbed. But edit_intent is a post-edit signal, not an ingest signal — there is no edit at first-ingest, so the arg is null/irrelevant for the ID-45 run. |
| Write-model fit (R1–R5) | Clean — content_history is app-written, NOT pipeline-written (write-model: pipeline NEVER writes content_history; flow.py write targets exclude it). No cross-target-FK hazard (R1 N/A). The arbitration write-site (TECH §4.2 step 5) already writes a content_history row per save — adding edit_intent is one more column on a row it already writes. | Poor — a sidecar in the walked path fights the “path = identity” model; the pipeline would re-read it on every walk and must be taught to treat it as metadata not content. R4 path-normalisation applies. | Poor for storage — a flow arg is a transient run input, not durable storage. It answers “how does the NEXT walk learn the intent” but NOT “where is the intent recorded” — it is a transport, not a store. |
| Who reads it | Diff-UI, audit, the re-classification trigger (read at the save site, passed to the next walk’s policy) | cocoindex on walk + any audit reader | cocoindex flow only |
| Audit/forensics (TECH §4.4) | Native — same row carries created_by, version, change_type; add edit_intent (+ optionally the per-actor arbitration_inputs jsonb) alongside. | Awkward — audit must read files, not rows. | None — transient. |
| Cost if chosen | One ALTER TABLE content_history ADD COLUMN edit_intent text (+ optional arbitration_inputs jsonb). C4 shape-only if landed pre-cutover (folds into the {64.7}/{64.8} window cleanly); cheap ALTER even post-cutover (no backfill — write-only forward). | Pipeline code change (new skip rule) + the freeze gate + a sidecar materialisation path that v1 otherwise DEFERS (PLAN §5 item 18 keeps Q&A sidecars DEFERRED-v1.1). | Plumbing with no durable record — needs (a) or (b) anyway for persistence. |
4.3 RECOMMENDATION — option (a) content_history column
Section titled “4.3 RECOMMENDATION — option (a) content_history column”Recommend (a): a content_history.edit_intent text column (+ optionally arbitration_inputs jsonb
for the per-actor inputs the TECH §4.4 audit contract wants). Rationale:
- It does NOT gate the re-ingest.
content_historyis app-written, not pipeline-written — the ID-45 run never touches it. The only re-ingest coupling is OQ-64-9 ({64.7} content_history disposition), and a new write-only column adds nothing to the renumber exposure {64.7} already plans for. By contrast the sidecar-.mdoption (b) does gate the run (§4.1) — it would force a pre-run pipeline skip-rule change for a v1.1-deferred materialisation path. Choosing (a) keeps the ID-45 critical path clean. - It fits the write-model. The arbitration write-site (TECH §4.2 step 5) already writes a
content_historyrow on each save;edit_intentis one more column on that row. No new file class, no R1 FK hazard, no R4 path-identity entanglement. - It serves audit + Diff-UI natively (§3) — the revision model Diff-UI reads already lives in
content_history. - It is the cheapest schema slice — one additive
ALTER, write-only forward, no backfill (every pre-existing history row legitimately hasedit_intent = NULL). - (c) is not a storage shape — it is a transport for the next walk; it still needs (a) or (b)
for persistence. Where the next walk needs to learn the intent (to apply the §8.2 re-run policy),
it reads it from the
content_historycolumn (a) at the write-back site, OR the write-back adapter (Spike#3) stamps it transiently — that is a transport detail T9 settles, orthogonal to storage.
On Liam’s sidecar-.md instinct: the instinct is sound for a different concern — a
human-readable, file-co-located revision/metadata artefact. But for the edit_intent label
specifically, the sidecar shape buys nothing the content_history column doesn’t, and it imports
the re-ingest freeze gate plus a v1.1-deferred materialisation path. The research run resolves to:
store edit_intent in content_history (a); do NOT use a sidecar .md for the intent label. If
Liam still wants file-co-located revision artefacts for human/diff reasons, that is a separate
v1.1 deliverable (PLAN §5 item 18, DEFERRED) and does not change the v1 storage decision.
4.4 The pre-cutover schema slice (the §6.2 “more than minimal” output)
Section titled “4.4 The pre-cutover schema slice (the §6.2 “more than minimal” output)”Under OQ-64-5 “structurally complete, based on ratified specs” ({64.8} gate G6), the §4.3 recommendation yields exactly ONE pre-cutover schema slice to ratify:
PRE-CUTOVER SLICE (proposed):
ALTER TABLE content_history ADD COLUMN edit_intent textwith a CHECK against the closed CV{cosmetic, data, structural}(NULL allowed — pre-edit-feature history), plus optionallyADD COLUMN arbitration_inputs jsonbfor the per-actor inputs (TECH §4.4). Lands in the {64.7}/{64.8} pre-re-ingest window so the handover DB is structurally complete for T9. Write-only forward — no backfill, no data migration. This is C4 shape-only (cheapALTER), and is cheap even if deferred post-cutover — so the slice is OPTIONAL-pre-cutover, not a hard gate. Recommend landing it pre-cutover anyway (zero cost, closes the C3 question ID-93 §4 raised, and {64.7} is already open).
This is the spec slice the §6.2 ratification asked the chain to surface. It is small and not
re-ingest-blocking — which is itself the answer to the ID-93 §6.8 “decide jointly with OQ-64-9”
framing: the joint decision is trivial once you see content_history is app-written, so the
edit_intent column is decoupled from the renumber exposure {64.7} handles.
5. External deps — track as cross_doc_links, NOT sibling dependencies
Section titled “5. External deps — track as cross_doc_links, NOT sibling dependencies”Per the brief + §3.3 sibling-only rule, these are cross-Task/cross-doc and must NOT become ID-59 sibling-subtask deps:
| Dep | What | Status | Where it bites | Track as |
|---|---|---|---|---|
| Spike#3 | write-back adapter contract (path resolution + byte write + intent stamp under COCOINDEX_SOURCE_PATH) | PENDING (PLAN §4.9 risk) — but largely answerable from the landed cocoindex-write-model.md R1/R4 | UC1/UC3/UC4 file write-back | cross_doc_link → themes/canonical-pipeline/reference/cocoindex-write-model.md + ID-31 PLAN §4.9 |
| Spike#10 | UC8 cross-record dedup substrate (cocoindex post-target-write @coco.fn vs mempalace KG vs hybrid) | PENDING (PLAN §4.9 risk; T12 + Spike#10) | UC8 only | cross_doc_link → ID-31 PLAN §4.9 + §4.8 scope-out; gates UC8 slice only |
| UC8 ratification | UC8 v1 Candidate A scope confirmation | PENDING | UC8 only | cross_doc_link |
| bl-74 | q_a_pair_history superseded_by + source_workspace_id columns — needed for UC8 merge-lineage; flipped ready, lands BEFORE ID-45 promotion ({64.8} gate G3) | ready | UC8 merge-lineage audit | cross_doc_link → docs/reference/backlog/74.md; coordinate at the UC8 slice |
{64.14} form rename (bid_*→form_*) | UC5 bid/form-response context | ratified, STEP-0 = form_* | UC5 response-context naming | cross_doc_link → ID-64 {64.14} |
Sibling-dependency note: the §4.3 storage slice and the per-UC write-back slices CAN be
sibling-ordered within ID-59 (e.g. the content_history.edit_intent slice before the UC1/UC4 slices
that stamp it). No cross-Task subtask dep is needed — all external deps are doc-level. No escalation
required.
6. Empirical verification (Q-EX2 / OQ-3 — pre-ratification)
Section titled “6. Empirical verification (Q-EX2 / OQ-3 — pre-ratification)”External-library / installed-surface claims, import-and-call verified 08/06/2026:
| Symbol / fact | Pinned version | Result |
|---|---|---|
cocoindex installed | cocoindex[postgres]==1.0.7 (requirements.txt:54) | PRESENT — import cocoindex; cocoindex.__version__ == '1.0.7'. NOTE: the write-model runbook verified against 1.0.3; the R1–R5 constraints are pin-version-stable (no 1.0.3→1.0.7 write-path break observed; pin bump = bl-252 promote, S324). |
cocoindex.connectors.localfs.walk_dir | 1.0.7 | PRESENT — hasattr(localfs, 'walk_dir') == True. Confirms the walked-layout model (§4.1). |
| Tiptap collab + Yjs deps | @tiptap/extension-collaboration@3.23.4, yjs@^13.6.30, y-prosemirror@^1.3.7 (package.json) | PRESENT — corrects TECH §T-1 “Yjs collab plugin not yet wired” (dep present; provider + intent-UX absent). |
content_history.edit_intent column | n/a (DB) | ABSENT — not in pre_squash CREATE TABLE (20260416102457:3485) nor any later ADD COLUMN migration. (This is the §4.4 slice to add.) |
source_documents.original_path column | n/a (DB) | ABSENT — real column is storage_path (flow.py:1185; migration …:4037). PLAN/TECH original_path is stale (§0). |
edit_intent / arbitrate TS symbols | n/a (code) | ABSENT — zero hits across lib/ app/ components/ types/ scripts/ supabase/ hooks/ contexts/. T9 is greenfield (§0). |
No ABSENT/SIGNATURE_DRIFT on an external API the spec relies on — the ABSENT rows above are the
intended-to-build surface (the slice §4.4 adds) and the stale-doc corrections (§0), not a blocker.
cocoindex 1.0.7 + localfs.walk_dir (the surfaces this RESEARCH’s §4.1 argument depends on) are
both PRESENT. Safe to ratify the RESEARCH on the §4.1 model.
7. Liam decision queue (recommendations — Orchestrator/Liam write the ledger, not this doc)
Section titled “7. Liam decision queue (recommendations — Orchestrator/Liam write the ledger, not this doc)”edit_intentstorage shape (§6.8 research run): RECOMMEND option (a)content_historycolumn, NOT the sidecar.md. The sidecar couples hard to the re-ingest source-layout freeze (§4.1) for a v1.1-deferred materialisation path; the column is app-written, decoupled from the renumber exposure, write-model-clean, and serves audit + Diff-UI natively. (§4.3)- Pre-cutover schema slice:
ALTER TABLE content_history ADD COLUMN edit_intent text(CHECK{cosmetic,data,structural}, NULL-allowed) + optionalarbitration_inputs jsonb. C4 shape-only, OPTIONAL-pre-cutover, not a hard gate — recommend landing it in the {64.7}/{64.8} window anyway (zero cost, closes ID-93 §4’s C3 question). Does NOT gate ID-45. (§4.4) - Correct the stale references before PRODUCT/TECH: write-back target is
source_documents.storage_path(NOToriginal_path); the arbitration substrate is greenfield code (only the rule spec landed S244);content_historyhas noedit_intent/actor_id/arbitration_inputscolumns today. (§0) - Diff-UI re-point: there is no
source_document_diffssubstrate to re-point off — build Diff-UI against the existingcontent_history/q_a_pair_historyrevision model. Diff-UI does NOT gate the §4 storage decision. (§3) - TECH §T-1 correction: Tiptap collab + Yjs deps ARE installed; what’s absent is the collab
provider wiring +
edit_intentcapture UX. (§1.1, §6) - External deps (§5): track Spike#3, Spike#10, UC8 ratification, bl-74, {64.14} as
cross_doc_links, not sibling deps. UC8 slice is the only one gated by Spike#10 + UC8 ratification +
bl-74. Spike#3 is largely pre-answered by the landed
cocoindex-write-model.mdR1/R4. - Right-sizing the chain: ID-59 IS behaviourally ambiguous + multi-subsystem (6 UCs + Diff-UI +
storage) → recommend authoring {59.2} PRODUCT (per-UC behaviour invariants + the Diff-UI UX) and
{59.3} TECH (write-back adapter contract + storage slice + the per-UC wiring against the
arbitration rule), then {59.4} PLAN (3 PLAN units → decompose; likely one slice per UC/UC-pair +
the storage slice + Diff-UI, well under the 25-subtask ceiling). The existing
TECH.md(arbitration rule) is an INPUT to {59.3}, not a replacement for it.
8. Open questions for Liam
Section titled “8. Open questions for Liam”- OQ-59-1: Confirm option (a)
content_history.edit_intentover the sidecar.mdinstinct (§4.3). If Liam still wants file-co-located revision artefacts, confirm that is a separate v1.1 concern (PLAN §5 item 18) and does not change the v1 storage decision. - OQ-59-2: Land the §4.4 slice pre-cutover (recommended, zero-cost) or defer post-cutover (also cheap)? Either is fine; pre-cutover closes ID-93 §4 cleanly.
- OQ-59-3:
content_items-without-source_documentsaudit (PLAN §4.9 / RATIFIED-S243 Item 10) — for content_items withsource_document_id IS NULL(e.g. MCPcreate_content_item, legacy import), is the edit-back behaviour (a) auto-create asource_documentwithconnector='mcp'storage path, or (b) fall back to KH-DB-only edit (no file write)? This is a per-UC1/UC4 behaviour the PRODUCT must pin; needs the prod sweep at PRODUCT time. - OQ-59-4: Is Diff-UI in scope for v1 PRODUCT, or does “retained for v1” mean a minimal content_history diff view only (deferring the richer markdown side-by-side to v1.1)? Affects {59.2} scope.
9. Sources cited
Section titled “9. Sources cited”| Source | Used for |
|---|---|
scripts/cocoindex_pipeline/flow.py (ACTIVE pipeline) — :1182 SOURCE_DOCUMENTS_SCHEMA, :1185 storage_path, :1346 _NON_FORM_SUFFIXES, :1355 .md→text/markdown, :1667 manifest skip, :1809 PK seed, :1971 storage_path=rel_path, :2877 COCOINDEX_SOURCE_PATH | §0, §4.1, §6 — walked-layout model + write surface |
scripts/cocoindex_pipeline/_coco_api.py :57 localfs | §4.1 — walk connector |
themes/canonical-pipeline/reference/cocoindex-write-model.md R1–R5, §1, §4 (BUG-B) | §2.1, §4 — uuid5 identity, no cross-target FK, sidecar=BUG-B class |
supabase/migrations/20260416102457_pre_squash_reconciliation.sql :3485 (content_history), :4037 (source_documents.storage_path) | §0, §4, §6 — actual DB shape |
specs/id-59-concurrent-edit-intent-arbitration/TECH.md T-1..T-5, §4.2/§4.4 | §0, §1.1, §4, §7 — arbitration rule (input, not replacement) |
specs/id-31-canonical-pipeline-implementation-plan/PLAN.md §4.9, §5 (items 5/18/19), §3/§8 | §2, §3, §5 — per-UC scope, Diff-UI, Spike#3/#10, UC8 |
specs/ID-93-pre-reingest-intent-gap/RESEARCH.md §4, §6.8 | §0, §4, §7 — C3 coupling framing, storage-shape research mandate |
docs/reference/tasks/ID-64.md {64.7}, {64.8} gate G6, {64.14} | §4.4, §5 — pre-cutover window, OQ-64-5/9 coupling, form rename |
themes/canonical-pipeline/reference/v1-completion-sequence.md Lane B/A, §2 | §0, §2 — sequencing, ID-83 boot-never-walks, pin context |
package.json :81–92, 131–132; requirements.txt :54 | §1.1, §6 — Tiptap/Yjs deps, cocoindex pin |
grep sweep (edit_intent/arbitrate over TS corpus; source_document_diffs over migrations) | §0, §1.1, §3, §6 — greenfield + absent-substrate confirmations |
End of RESEARCH. Recommendations PENDING Liam (§7/§8). No implementation, no DDL, no ledger edits performed.