docs(#841): document compose/diff bidirectional invariant - #862
docs(#841): document compose/diff bidirectional invariant#862fullsend-ai-coder[bot] wants to merge 2 commits into
Conversation
Add docs/contributing/harness-composition.md documenting the bidirectional invariant between merge/compose functions in compose.go/forge.go and their diff counterparts. The diff functions (DiffHarness et al.) were removed with the scaffold agent extraction per ADR 0045, but the constraint remains architecturally important: any re-introduced diff function must mirror current merge semantics to preserve the round-trip property. The document includes: - Explanation of the bidirectional invariant and why it matters (round-trip corruption risk, as demonstrated by PR fullsend-ai#5450) - Tables of all current merge functions with their semantics, separated by context (base: composition vs runtime forge resolution) to clarify the semantic differences between mergeForgeConfigInto and mergeForgeConfig - Actionable checklist that gates on diff function existence before requiring diff-side updates - Guidance on when the diff side is unaffected Also adds a row to the AGENTS.md guidance table so agents discover this document when modifying internal/harness/ merge or diff functions. Note: pre-commit could not run (network restriction in sandbox). The post-script runs pre-commit authoritatively. Closes #841
|
🤖 Finished Review · ✅ Success · Started 9:44 AM UTC · Completed 9:59 AM UTC |
ReviewFindingsMedium
Low
Previous runReviewFindingsMedium
Low
Labels: PR adds new contributing documentation and modifies AGENTS.md guidance table |
|
/fs-fix |
|
🤖 Finished Fix · ✅ Success · Started 10:32 AM UTC · Completed 10:37 AM UTC |
- mergeBaseIntoChild: note PreflightCheck carry-forward exception in
pointer-struct semantics description
- mergeForgeConfig: correct skills description from "appended" to
basename-based dedup via mergeSkills
- AGENTS.md: rephrase trigger to clarify diff functions do not currently
exist ("or adding diff functions" instead of "or diff functions")
Addresses review feedback on #862
🔧 Fix agent — iteration 1 (human-triggered)Addressed all 4 review findings. Fixed 3 documentation accuracy issues (PreflightCheck carry-forward exception, mergeForgeConfig skills dedup semantics, AGENTS.md stale trigger wording). Disagreed with 1 informational finding about protected-path labeling (already handled by existing label). Fixed (3):
Disagreed (1):
Tests: passedNext steps:
|
|
🤖 Finished Review · ✅ Success · Started 10:40 AM UTC · Completed 10:55 AM UTC |
| | `mergeBaseIntoChild` | Top-level harness merge | Scalars: child overrides; slices: concatenated; maps: merged (child wins); pointer structs: child replaces if non-nil (except `PreflightCheck` carry-forward — see `mergeForgeConfigInto` below) | | ||
| | `mergeSkills` | Skill path deduplication | Base + child, child overrides base by basename | | ||
| | `mergeHostFiles` | Host file deduplication | Base + child, child overrides base by dest path | | ||
| | `mergeForgeBlocks` | Per-platform forge merge | Key-by-key merge; each platform uses `mergeForgeConfigInto` | |
There was a problem hiding this comment.
[medium] Incomplete documentation with correctness surface area
The merge semantics tables for mergeBaseIntoChild, mergeForgeConfigInto, and mergeForgeConfig omit the Env field (EnvConfig), which all three functions merge with differing precedence rules. mergeBaseIntoChild and mergeForgeConfigInto use mergeEnvFrom(src, false) (child/dst wins), while mergeForgeConfig uses mergeEnvFrom(src, true) (forge/src wins). Since the document serves as the authoritative reference for implementing diff counterparts, omitting Env could cause a diff implementor to miss a field entirely.
Suggested fix: Add Env merge semantics to each of the three merge function rows in the tables.
| [ADR 0045](../ADRs/0045-forge-portable-harness-schema.md) introduced `base:` | ||
| composition with field-level merge semantics. The merge functions have an | ||
| architectural inverse: diff functions that extract the delta between a composed | ||
| result and its base. ADR 0045 (Consequences, "Bidirectional composition") notes |
There was a problem hiding this comment.
[low] Internal consistency
The sentence attributing the normative constraint ('any re-introduced diff function must mirror the current merge semantics') to ADR 0045 is inaccurate. The ADR records the historical fact that DiffHarness was removed; the normative constraint is this document's own addition.
Suggested fix: Rephrase to clearly separate the ADR citation from the document's own constraint.
Summary
Documents the bidirectional invariant between merge/compose functions (
compose.go,forge.go) and their corresponding diff functions ininternal/harness/. This constraint was previously only documented in ADR-0045's Consequences section, which agents do not read during normal operation — causing a round-trip regression on PR fullsend-ai#5450 that took 6 iterations to resolve before being abandoned.Related Issue
Closes #841
Changes
docs/contributing/harness-composition.mdwith:base:composition functions (compose.go) and runtime forge resolution functions (forge.go), clarifying the semantic differences betweenmergeForgeConfigIntoandmergeForgeConfiginternal/harness/"Testing
Checklist
!for breaking changes)Closes #841
Post-script verification
agent/841-compose-diff-invariant)c887fc47c59d8b87b5282ca44044d2933d30df41..HEAD)