Tracker-sync: project Flow spec dependencies as blocked-by relations (Linear + GitHub) — fn-64#176
Conversation
…relation + bare-N identifier (fn-64.1)
…ation/listIssueRelations + relation struct
- Add the two relation methods to the transport table (now 8 methods), tagged fn-64.3/fn-64.4
- New `relation` struct {from, to, type, source} with source provenance semantics
- Direction convention stated once: blocked-by = current issue blocked by dep issue
- Read-before-write idempotency (mandatory) + never-delete-non-ours provenance (ledger / fenced marker)
- Cross-link to fn-64.1 depRelations ledger, fn-64.4 body-merge fenced-block exclusion, completed-blocker rule
Task: fn-64-tracker-sync-project-flow-spec.2
…e blockedBy + GraphQL issueRelationCreate, read-before-write dedup - linear-mcp.md: setIssueRelation via save_issue blockedBy (append-only, live re-verified 2026-06-17) + listIssueRelations via get_issue includeRelations:true; read-before-write rationale - linear-graphql.md: issueRelationCreate(type:blocks) with correct operand inversion (issueId:B blocker, relatedIssueId:A blocked); dedup queries BOTH relations+inverseRelations (explicit first:) canonicalized to one direction - linear-ladder.md: relation pair routed through MCP/GraphQL/no-op ladder; per-capability MCP-schema-drift fallback (MCP absent -> GraphQL if LINEAR_API_KEY else noop); parity table + no-op rung extended to eight methods - never-delete-non-ours: setIssueRelation only ever adds; depRelations ledger is provenance authority Task: fn-64-tracker-sync-project-flow-spec.3
…locked_by deps + fenced #N body-block fallback
- Native path: GET/POST /repos/{o}/{r}/issues/{n}/dependencies/blocked_by via gh api
(API 2026-03-10, GA Aug 2025); issue_id resolved to numeric DB id; 50/type cap;
blocked_by-only-writable; DELETE optional/no-delete-default (R6)
- Feature-detect GET probe ([] = available-empty, 404/410 = fallback)
- Fallback: provenance-fenced <!-- flow:deps --> #N body block, rewritten only
inside markers, idempotent (R3); #N/owner-repo#N/bare-N parse on read
- Read-before-write dedup on both paths; never-delete-non-ours (ledger native,
fence fallback); completed-blocker stays visible, no ready=true regress (R5)
- Capability-parity table + relation fidelity note (native vs fenced = identical
normalized relation[]) extend the R13 transport-blind proof
- All native facts verified vs official REST docs + live gh api probe (2026-06-17)
Satisfies R2, R3.
Task: fn-64-tracker-sync-project-flow-spec.4
…numeric issue_id), not -f (string) — would 422 Review: -f/--raw-field sends issue_id as a JSON string; GitHub requires a numeric DB id. -F/--field types bare integers as JSON numbers. Task: fn-64-tracker-sync-project-flow-spec.4
… review fix) Task: fn-64-tracker-sync-project-flow-spec.4
Task: fn-64-tracker-sync-project-flow-spec.4
- steps.md: projectDepRelations on push + reconcile (modelled on projectReadiness); edge enumeration via sync list-dep-relations, missing-link warnings (fn-57 grammar), read-before-write project + ledger provenance, completed-blocker keep-not-regate (R5), strictly-additive never-clobber, collision-before-per-side-rules → defer + queued (R6/R10), self-edge/cycle handling no-traversal (R8), transport-unreachable noop, real receipt enum - body-merge.md: Step 0.5 tracker-body-for-merge transform — strip <!-- flow:deps --> at the hash boundary before all baseHashTracker/mergeBaseTracker/fetch comparisons; Fixture E oracle (R10) - SKILL.md: flowctl-owns/skill-owns table rows + relation interface + dependency-projection boundary (additive, no re-gate, no traversal, transport-blind) Task: fn-64-tracker-sync-project-flow-spec.5
… + 2.1.0 bump + codex mirror - docs/tracker-sync.md: new Dependency-projection section (direction, per-adapter fidelity, idempotency, provenance ledger, body-merge ownership, completed-blocker, warnings, collision rule) - docs/flowctl.md: list-dep-relations / set-dep-relation / clear-dep-relation subcommands + bullets - GLOSSARY.md: dependency projection, provenance ledger, completed-blocker rule - CHANGELOG.md: 2.1.0 feature entry (fn-64 / FLOW-14) - scripts/bump.sh minor 2.0.0 -> 2.1.0 across all manifests; README badge - codex mirror regenerated (sync-codex via bump.sh) — tracker-sync references .2-.5 Task: fn-64-tracker-sync-project-flow-spec.6
Task: fn-64-tracker-sync-project-flow-spec.6
…rected tracker edge, not dep_spec — stale after relink (fn-64 R7/R9) Completion-review finding: projected derived from dep_spec membership would report true for an edge whose endpoint was relinked to a different issue. Now computes the edge key from both current tracker ids + requires both linked. Adds relink regression test.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 351393fafd
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…iewer + @codex review trigger
…- flow:deps --> block on full-body update (fn-64, PR #176 review) renderFlowToTracker never emits the dep block, so a raw full-body gh issue edit wiped it — projectDepRelations then misread the ledgered edge as a remote removal and queued a false collision (self-deleting projected deps). writeIssue UPDATE now reads the current body + carries the fenced block forward (write retains, merge strips per body-merge Step 0.5). Codex mirror regenerated.
|
@codex review |
|
Codex Review: Didn't find any major issues. More of your lovely PRs please. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
…ent as the silence signal (found landing PR #176)
What & why
Tracker-sync projects a spec's body, status, and comments to the board — but dependency edges stayed local-only:
depends_on_epicswas invisible on Linear/GitHub, so the board showed independent issues even when Flow knew one blocked another (this bit SapienXT — relations had to be hand-added as a stopgap).This adds dependency projection: a
depends_on_epicsedge between two linked specs becomes a blocked-by relation between their issues — on both Linear and GitHub (scope extended from the original Linear-only issue per @gmickel) — idempotently, provenance-tracked, and never clobbering a relation a human added by hand.One transport-blind hook (
projectDepRelations, modelled on readiness projection) drives both adapters; only fidelity differs.R-ID coverage
save_issue blockedBy+ GraphQLissueRelationCreate type: blocks)blocked_bydeps (GA Aug 2025) + fenced<!-- flow:deps -->body-block fallbackrelations+inverseRelationscanonicalized)donedependency stays visible but never re-gatesready=truedepRelationsledger;list-dep-relations;projectedkeyed off the directed tracker edgesetIssueRelation/listIssueRelations); self-edge skip; cycles = direct edges, no traversalNid, self-edge, relinktrackerBodyForMergestrips before hash/merge-base; collision→queued/defertracker-sync.md,flowctl.md, adapter refs, body-merge), GLOSSARY, CHANGELOG, 2.1.0 bump, Codex mirror, flow-next.devCritical changes — where to look
plugins/flow-next/scripts/flowctl.py(+~300) —depRelationsledger indefault_spec_tracker_state(), opaque hashed edge keys (never inlines a raw issue key — auto-linkify pitfall),sync list-dep-relations/set-dep-relation/clear-dep-relation, bare-Ntracker-identifier widening.dep_statusis the local dep-spec status (not a remote fetch);projectedkeys off the directed tracker edge so a relinked issue reads un-projected.skills/flow-next-tracker-sync/references/{adapter-interface,linear-mcp,linear-graphql,linear-ladder,github,body-merge}.md— the relation transport contract + both adapter rungs (docs-as-implementation: the adapter is the procedure the host agent runs).body-merge.mdgains thetrackerBodyForMergestrip so the GitHub fenced block never reads as tracker divergence.skills/flow-next-tracker-sync/{steps.md,SKILL.md}—projectDepRelationson push + reconcile: warnings, completed-blocker, never-clobber, collision-before-per-side (queued/defer), self/cycle.plugins/flow-next/tests/test_tracker_sync_state.py(+~240) — pure-stdlibunittest; covers the ledger, idempotency, missing-link, completed-blocker, bare-N, self-edge, and the relink regression (projected→false after a dependency relinks).plugins/flow-next/codex/…); docs + GLOSSARY (3 terms) + CHANGELOG; plugin 2.0.0 → 2.1.0. flow-next.dev updated in its own repo (gmickel/flow-next.dev@c9d407b).Decision context
[[gh-api-f-stringifies-numeric-body-2026-06-17]]— GitHub nativeblocked_byPOST needsgh api -F(numericissue_id), not-f(string) → 422. Caught by the fn-64.4 rp review; fixed + memory'd.Verification
python3 -m unittest discover -s plugins/flow-next/tests→ 1088 tests OK (2 skipped).flowctl sync list-dep-relations fn-64resolves fn-52→FLOW-3 / fn-57→FLOW-10 / fn-58→FLOW-7,dep_status=done,projected=false.gh apiprobe confirmed the GitHub nativeblocked_byendpoint shape againstgmickel/flow-next.projectedcorrectness gap + flow-next.dev.scripts/bump.sh minorapplied across all five manifests.🤖 Generated with Claude Code via
/flow-next:make-pr