F5 — Cross-rung git-native persistence format + round-trip to the Gitea substrate rung #14
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Cross-rung git-native persistence format + Gitea round-trip: graduate the
inner-loop
.threads/sidecar (threads · attributions · proposals on sharedanchors/Provenance) from "the editor's private shape" into the cross-rungcontract — the one shared git-native model the three-rung ladder (editor →
Gitea substrate → rfc-app) reads and writes — and prove it with a real
round-trip: the coauthoring record travels with ordinary
git push/pulland survives being read, displayed, and written-back from outside the editor
rung without re-homing.
Problem / pain
The epic's promise is that the coauthoring record is "persisted git-natively so
it is serverless, durable, and portable up to the Gitea rung later without
re-homing" — but portability has never been exercised. Every graduated spec
deliberately deferred it: the F2 design called its format "the inner-loop
shape, not yet the cross-rung contract" (coauthoring-inner-loop.md §9
OPEN→F5), and F3/F4 each routed "may re-home
attributions[]/proposals[]" here. Today nothing outside the extension can consume thesidecar with any guarantee: there is no published schema contract, no
compatibility/versioning rules for readers that aren't this codebase, no
cross-rung identity story (
Provenance.idis a local$USER, not a forgeidentity), and no answer for what happens when a second writer — a teammate's
editor via
git pull, or a future Gitea-rung surface — touches the samerecord. Until F5, the ladder's "git is truth; the surfaces are clients"
architecture is an assertion, not a property.
Who feels it
human enters: clone the repo elsewhere and the record must arrive intact and
merge sanely.
both are specified as clients of this same model ("continuity of substrate —
no migration cliff"); they can only be built against a contract that exists.
corpora): each becomes coauthorable only if the record format is consumable
beyond one editor.
Desired outcome / value
The sidecar format is a published, versioned, validated contract — the
cross-rung schema, not an implementation detail: documented field-by-field,
with explicit schema-evolution rules (what a
schemaVersionbump means, whatunknown-field/unknown-version readers must do), a cross-rung identity
story for
Provenance, and a defined merge/conflict story for concurrentwriters. A demonstrated round-trip proves it: the record a coauthoring
session produces is pushed, consumed and modified by a non-extension client
(the Gitea-rung posture), pulled back, and the editor renders the result
correctly — re-anchored or honestly orphaned, never corrupted, never
silently re-homed. This converts the epic's portability promise into a tested
property and unblocks the rfc-app#46 brainstorming on the substrate side.
Acceptance — "done right"
format: every section (
anchors,threads,attributions[],proposals[],Provenance,schemaVersion), its invariants (stable keyorder, pending-only proposals, fingerprint semantics), and the
compatibility rules — how readers treat unknown fields and newer/older
schemaVersions, and what is allowed to change without a major break.Provenancecan carry a forge-resolvableidentity (not just a local username) for both human and agent authors,
without breaking existing sidecars.
(a) pushed and pulled through ordinary git with full fidelity (byte-stable
serialization holds), (b) modified by a non-extension writer (the
Gitea-rung posture — e.g. a thread reply appended out-of-editor per the
contract), and (c) on pull, the editor renders the out-of-editor change
correctly: new messages appear, anchors re-resolve or orphan per INV-1,
nothing is silently dropped or rewritten.
same sidecar produce a merge that is human-resolvable per the contract
(stable ordering limits the blast radius), and the documented resolution
rules are validated by a test, not just asserted.
schema and/or a small validator) that any rung can run against a sidecar
file; the extension's own unit suite uses it.
handling, and the merge cases; host E2E covers the out-of-editor-change
→ pull → render path (the F2/F3/F4 external-change pattern; no LLM in CI).
Scope / non-goals
In scope: the cross-rung contract document + versioning/compatibility
rules; any format changes the contract forces (re-homing or extending sidecar
sections, a
schemaVersionbump if break-class changes are needed); theProvenancecross-rung identity extension; the out-of-editor write +round-trip proof and its tests; a rung-neutral validation artifact.
Out of scope (deferred, not forgotten): the Gitea-side substrate
primitives themselves (file-level discussions UI, LLM participants,
native proposal layers — rfc-app#46's build, on its own tracker); any rfc-app
work; a sync daemon or server (git push/pull IS the transport); file
rename/move tracking (inner-loop §9 OPEN→later, unchanged); multi-file
orchestration; rejected-proposal history trails (propose-accept §9 OPEN→later
— unless the contract work resolves it for free).
Assumptions · constraints · dependencies
the three acceptance pillars shipped in F2 #4, F3 #6, F4 #12). Blocked
by: #12 (F4 — shipped; PR #13). Feeds: the rfc-app#46 substrate
brainstorming (the contract is its input) and the rfc-app rung above.
shared git-native model — git is truth; the surfaces are clients. F5 is
the editor rung's half of that bargain: make the model consumable beyond
the editor. "No migration cliff" is the strategic outcome F5 must not
foreclose.
blank page): per-document
.threads/<path>.jsonsidecar; sharedanchorsmap +
Fingerprint(text/before/after/lineHint);Provenance(
kind: human|agent, agent carries sdk/model/sessionId);threads[]/attributions[](state, not history) / pending-onlyproposals[](INV-13);
SCHEMA_VERSION = 1; stable key order + trailing newline(INV-2) precisely so diffs/merges stay sane; extension is currently the
sole writer — F5 deliberately ends that assumption.
brainstorming session; this Feature consumes its reviewed Solution Design:
(a) substrate: does the sidecar stay the canonical cross-rung carrier
(the F2 decision rejected git notes/trailers for the inner loop — does
that hold cross-rung, per the epic's "
.threads/sidecar vs. git notesvs. trailers" fork)? (b) contract form: prose spec vs. JSON Schema vs.
both, and where it lives (content repo vs. engineering schemas/); (c)
identity: how
Provenance.idmaps to forge identities (email? forgeusername? signed?) for humans and agents; (d) merge semantics: per-
section merge rules vs. whole-file last-writer + repair, and whether the
contract mandates a merge driver; (e) round-trip proof shape: what
plays the Gitea-rung writer in CI (a script appending a thread reply per
the contract is the cheapest honest stand-in); (f) versioning: does
the identity extension fit additively in
schemaVersion1 or force 2,and the deprecation rules either way.
Source / signal
Epic #1 (
coauthoring-plugin-on-cline) decomposition item F5 — Git-nativepersistence format (
.threads/sidecar vs. git notes vs. trailers) +round-trip to the Gitea rung (#46); the graduated Solution Designs'
deferrals —
coauthoring-inner-loop.md§9 OPEN→F5 ("F2's format is theinner-loop shape, not yet the cross-rung contract"),
coauthoring-attribution.md§9 OPEN→F5,coauthoring-propose-accept.md§9OPEN→F5 ("the proposed→ratified→attributed story is what crosses rungs");
architecture lineage
ben.stull/rfc-app#48(the ladder) andben.stull/rfc-app#46(the Gitea-substrate rung: "continuity of substrate —no migration cliff"; "git is truth"). Builds on F4 shipped in #12 (PR #13,
session
vscode-cowriting-plugin-0012). Captured in sessionvscode-cowriting-plugin-0013.Priority (WSJF)
Provisional: Value medium-high (converts the epic's portability promise
into a tested property; second-writer safety matters the moment a teammate
clones) · Time-criticality low-medium (no Gitea-rung deployment exists
yet; rises to P1 when rfc-app#46 work is scheduled) ·
Opportunity-enablement high (the contract is the prerequisite input for
the rfc-app#46 substrate brainstorming and the whole ladder) ÷ Size
medium-large → P2.
Decomposition (Feature → slice checklist)
cross-rung identity; merge semantics; round-trip proof shape; versioning)
— consume the follow-on Solution Design.
the design picks one), including compatibility + merge rules.
Provenance; any re-homing/section changes;schemaVersionhandling),with migration/compat tests for existing sidecars.
write → push/pull → out-of-editor modify → pull → render
(re-anchor/orphan honest), plus concurrent-writer merge cases.
Solution notes (optional — NOT a design)
The shipped format already has cross-rung virtues the contract can simply
ratify: plain pretty JSON, stable key order, trailing newline, shared
anchors, state-not-history sections — all chosen in F2 for mergeability.The F2 decision table already weighed git notes (bind to commits, weak
tooling, no default push) and commit trailers (only fit diffs) against the
sidecar — the cross-rung question is whether those trade-offs change when the
reader is a forge, not whether to relitigate the inner loop.
Provenancehasroom for an additive identity field (serializer omits optionals — F4
precedent). The engineering repo's central-schema discipline
(
schemas/app.schema.json, versioned centrally, apps conform) is the obvioustemplate for where/how the contract is published — and
wiggleverse/engineering#19(validated collection metadata) is the adjacentconversation rfc-app#46 names. All non-binding — the forks above are the
design session's to resolve.