Repository navigation
feat(analyst): implement independent Branch workspaces and local graph changes #1352
Description
Outcome and scope
Implement this bounded portion of canonical M11 tracker #1347. Documentation integration #1346 is a prerequisite. Source coverage: Core §§3, 6, 14; Semantics §§7–12, 19–23, 31–32.
Requirements and acceptance criteria
-
Create a Branch from a whole Project, Slice, Branch, or historical Version; freeze immediate parent/base, ultimate Project lineage, selection definition/membership, evidence and ontology context, creator and creation time.
-
Inherit graph-object UUIDs without renaming conceptual entities. Implement one coherent Branch graph view for local add/modify/suppress/replace/reclassify operations, with independent parent and child state.
-
Explicit graph suppression changes Branch query/analyst results while parent graph and historical Versions remain unchanged. Suppressing an assertion must not delete arbitrary referenced graph objects.
-
Expose Reference separately from Bring into Branch; only the latter expands active research. Preserve exact origin Version for added context and show object-level inherited/local/suppressed status.
-
Support local ontology extensions and classification changes under exact composition/scoped validation without changing parent authority.
-
Expose research genealogy and named Versions, and prove small Slice Branches share selected immutable content without copying or indefinitely retaining the entire ancestor. Measure creation work and retained bytes after parent evolution and cleanup; preserve selected evidence/ontology/baseline closure, and disclose historical expansion unavailable outside retained history.
-
Branches share their Project durable container and
CURRENTauthority under ADR 0032, while parent and child research evolve independently. Reuse feat(storage): add immutable research Versions and dependency retention #1350's authenticated participants, locks and receipts; Forks, not Branches, create separate Project authority. -
Preserve immutable original origin separately from per-object/field incorporated revision baselines and stable contribution identities for feat(analyst): expose provenance-aware semantic research comparisons #1354/feat(analyst): preview and selectively incorporate upstream research changes #1355/feat(analyst): implement selective Proposals and provenance-preserving acceptance #1356. Selected updates may later advance only selected baselines; immutable graph UUID, revision and operation identities are not interchangeable.
-
Implement Branch restoration using feat(storage): add immutable research Versions and dependency retention #1350's scoped contract: restore selected historical research into a new current Version of that Branch only, preserving the parent, sibling/child Branch heads, and Project acceptance/operation history. Reject unsupported scope before mutation; a generic whole-container checkpoint revert is not a Branch restore.
-
Own and prove the real two-Branch restoration/isolation scenario through the Rust public facade, with at least two Branches and independent parent changes, including reopen. feat(storage): add immutable research Versions and dependency retention #1350's participant/head fixtures establish the foundation but do not satisfy this criterion. Integrate feat(storage): add immutable research Versions and dependency retention #1350's retention-root lifecycle and distinguish frozen Version content from separately presented current acceptance context. Actual Proposal/acceptance composition and accept→restore→retry belong to feat(analyst): implement selective Proposals and provenance-preserving acceptance #1356 and are not closure prerequisites here; test(analyst): certify the full research journey and associated-project contract #1358 later certifies the full cross-surface journey.
Implementation grounding
Existing ownership: graphforge-api workspace lifecycle and graph publication, graphforge-storage authenticated sharing, graphforge-ontology composition reuse.
Use docs/engineering/analyst-ux.md, docs/book/architecture/research-workspaces.md, and the relevant integrated knowledge/storage/ontology/portability docs. Those docs were delivered by merged PR #1368 for #1346; the second-pass refinements in this issue must be reflected in the owning docs alongside implementation. Planned requirements are not implementation evidence.
Rust owns all behavior. Deliver the public facade operation(s) and thin Python, Node, and CLI parity appropriate to this outcome, including explicit request/result/error contracts, relevant schema/capability registration and non-Cypher surface inventory updates. Data-bearing output is Arrow; control/metadata/lifecycle output follows the existing contract.
Prerequisites: #1346, #1350, #1351. Native blocked-by relationships are the scheduling authority. This issue is a native child and blocker of #1347.
Completion scenario
Given a frozen story Branch, when an analyst changes a character, suppresses an inherited edge and adds another story, then only that Branch changes and all inherited/imported identities and origin Versions remain inspectable.
Given cancellation, invalid input or conflicting state, when the operation fails, then it returns an actionable structured error and leaves no partial authoritative mutation; read-only operations never mutate.
Given Branch A at an old retained Version, later parent changes, and an independently advanced Branch B, when restoring A, then only A's selected research state is restored into a new Version; parent state, B and other Branch heads remain unchanged after reopen.
Validation
Project/Slice/Branch/historical creation; parent vs Branch Cypher and analyst results; UUID equality; nested genealogy; expansion vs reference; independent ontology; durable reopen; pre-linearization cancellation/conflict refusal and post-linearization committed-state reconciliation; representative large-parent/small-Branch bounds.
Run targeted Rust/domain tests during development, then the applicable Bazel/CI Gate and native binding checks for the changed surface. Rebuild natives before binding tests. Durable claims require actual reopen/recovery on an admitted filesystem; the overlay-root Cloud environment cannot supply that evidence. Do not use skipped tests, logical plans or wrappers as end-to-end proof.
Diagnostics, security, and docs
Reuse structured errors and bounded receipts with identity, phase, scope and safe cause information. Do not log credentials, source content or personal annotations. Preserve explicit context selection, dependency validation and private/unselected content boundaries. Access-policy metadata is not remote authentication or authorization enforcement.
Update the owning docs and any public contract/inventory in the same PR; distinguish Designed from implemented behavior. Each issue owns its regression coverage before the final integrated journey.
Non-goals
Canonical knowledge status, upstream synchronization, proposal acceptance.
Associated projects such as XYG and graphforge-nextjs, applications and peer extensions own their UX/hosting/access enforcement; none becomes a Core dependency. No unrelated scope or publication-only close gates.
Activity
feat: add independent native Branch workspaces (CurateLabs#1545)