You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Since #251, every create-time and lifecycle relation must stay inside one Effort: derives_from, supersedes, invalidates, cites, resolved_by, mitigated_by, evidence and rejected_by. #251 correctly removed an
inconsistency: commits used to succeed that reads then hid. The resulting rule,
though, forces an uncomfortable choice whenever one coherent piece of work
builds on reasoning recorded in several Efforts. That is the normal case once a
project has domain Efforts, such as "graph semantics", "geometry engine",
"editor UX" and "export".
A downstream project planned a feature: a family of distortion nodes. It needed
six durable Decisions. Their causes lived in four existing Efforts:
node registry contracts and cache identity (graph Effort);
authoritative geometry, tolerance semantics, the packed path format, and an open
"excessive geometry" Risk (geometry Effort);
"graph is the only authoring surface" and "distinguish preview from
authoritative geometry" (editor Effort);
"define export behavior for every effect" (export Effort).
The options were:
Create a feature Effort. The feature is then readable as one thread, but
no Decision can derive_from its real causes. Links degrade to ids written in
prose, which reads can't follow, the validator doesn't check, and Retract
doesn't strip.
Split the feature across domain Efforts so that each Decision can link to
its causes. We chose this: 3 Decisions in the graph Effort, 2 in the geometry
Effort and 1 in the editor Effort. The feature now has no single place to read
it. Recall needs three Effort-scoped queries plus prose cross-references, and
links to the export Effort's Constraint are still impossible.
Duplicate or broaden. Copy upstream Constraints and Decisions into the
feature Effort, or widen a domain Effort until everything fits.
All three options cost specificity. Option 2 is also the direct cause of Effort bloat and scope creep:
Effort size: domain Efforts become catch-alls for every feature touching
them. They reach the 25-record read cap sooner, and each feature's reasoning
is interleaved with unrelated threads.
Risk mitigation:MitigateRisk can only point at a Decision in the Risk's
Effort. A feature Decision that actually mitigates a domain Risk must either
move into that domain Effort or leave the Risk permanently open.
Placement pressure: an agent optimizing for linkability picks the Effort
with the most linkable causes, not the Effort that best describes the work.
Effort boundaries stop meaning "one coherent thread".
Proposed direction
Keep the lifecycle edges effort-local. supersedes, invalidates, resolved_by, mitigated_by and rejected_by change another record's state,
so the #251 boundary is right for them. Add a reference path for causal
context:
Cross-Effort derives_from (and possibly cites) as read-only references.
Allow them to point at a record in another Effort.
Never write reverse projections into the foreign record.
Validate target existence at create time.
Render them in digests as foreign checkpoints with their Effort id and
current state, followed only with an explicit flag such as relations --include-foreign.
Retract strips them globally, or reads report them as dangling explicitly
rather than silently dropping them.
Or declared Effort dependencies. An Effort declares depends_on: [<eff-id>], and cross-Effort causal edges are allowed only into declared
dependencies. This keeps the graph intentional and gives reads a bounded
frontier.
Cross-Effort mitigation. Allow MitigateRisk to reference an accepted
Decision in a dependent Effort, or document the intended pattern for a feature
Decision that mitigates a domain Risk.
Acceptance
A feature Effort can hold its own Decisions and link each to accepted records
in the domain Efforts it builds on, without moving records or duplicating
them.
Bounded reads stay bounded. Foreign references cost at most one checkpoint
line each and are never expanded implicitly.
Describe the problem
Since #251, every create-time and lifecycle relation must stay inside one Effort:
derives_from,supersedes,invalidates,cites,resolved_by,mitigated_by,evidenceandrejected_by. #251 correctly removed aninconsistency: commits used to succeed that reads then hid. The resulting rule,
though, forces an uncomfortable choice whenever one coherent piece of work
builds on reasoning recorded in several Efforts. That is the normal case once a
project has domain Efforts, such as "graph semantics", "geometry engine",
"editor UX" and "export".
Versions:
flatbread@1.2.0,@flatbread/proof@1.2.0.Real-world example
A downstream project planned a feature: a family of distortion nodes. It needed
six durable Decisions. Their causes lived in four existing Efforts:
"excessive geometry" Risk (geometry Effort);
authoritative geometry" (editor Effort);
The options were:
no Decision can
derive_fromits real causes. Links degrade to ids written inprose, which reads can't follow, the validator doesn't check, and
Retractdoesn't strip.
its causes. We chose this: 3 Decisions in the graph Effort, 2 in the geometry
Effort and 1 in the editor Effort. The feature now has no single place to read
it. Recall needs three Effort-scoped queries plus prose cross-references, and
links to the export Effort's Constraint are still impossible.
feature Effort, or widen a domain Effort until everything fits.
All three options cost specificity. Option 2 is also the direct cause of
Effort bloat and scope creep:
them. They reach the 25-record read cap sooner, and each feature's reasoning
is interleaved with unrelated threads.
AcceptDecisionrejectSiblings: truedefault more destructive, because more unrelatedproposals sit together (see proof: AcceptDecision rejectSiblings default rejects unrelated proposals across the whole Effort #277).
MitigateRiskcan only point at a Decision in the Risk'sEffort. A feature Decision that actually mitigates a domain Risk must either
move into that domain Effort or leave the Risk permanently open.
with the most linkable causes, not the Effort that best describes the work.
Effort boundaries stop meaning "one coherent thread".
Proposed direction
Keep the lifecycle edges effort-local.
supersedes,invalidates,resolved_by,mitigated_byandrejected_bychange another record's state,so the #251 boundary is right for them. Add a reference path for causal
context:
derives_from(and possiblycites) as read-only references.current state, followed only with an explicit flag such as
relations --include-foreign.Retractstrips them globally, or reads report them as dangling explicitlyrather than silently dropping them.
depends_on: [<eff-id>], and cross-Effort causal edges are allowed only into declareddependencies. This keeps the graph intentional and gives reads a bounded
frontier.
MitigateRiskto reference an acceptedDecision in a dependent Effort, or document the intended pattern for a feature
Decision that mitigates a domain Risk.
Acceptance
in the domain Efforts it builds on, without moving records or duplicating
them.
line each and are never expanded implicitly.