Skip to content

fix(boatstack): resolve managed-PR task graph in both feature layouts - #137

Merged
bigboateng merged 2 commits into
mainfrom
boatstack/fix-tasks-layout-fallback
Jul 23, 2026
Merged

fix(boatstack): resolve managed-PR task graph in both feature layouts#137
bigboateng merged 2 commits into
mainfrom
boatstack/fix-tasks-layout-fallback

Conversation

@bigboateng

Copy link
Copy Markdown
Contributor

Problem

managedPRSources (pr.go) hardcoded the task graph as <feature>/compiled/tasks.json with no fallback and handed it to CheckApprovalLock, which hashes whatever TasksPath it is given (plan.goSHA256File(options.TasksPath)). A feature whose plan.lock.json was written in the older feature-root layout (ActivatePlan with OutDir = <feature>, so tasks.json sits at the feature root and there is no compiled/ dir — e.g. cta-transport-feedback) has no compiled/tasks.json. SHA256File fails, the task_graph label mismatches, and managed PR preparation returns "managed PR requires a current build lock" — blocking the ship-gate even though build/test/review all passed.

The very next block already resolved evidence across both layouts; the task graph was the only artifact missing that two-layout resolution.

Fix

Introduce one shared featureArtifactPath resolver (canonical location first, alternate as fallback) and route both the task graph (compiled canonical → root fallback) and evidence (root canonical → compiled fallback) through it, so the two layout resolutions can never silently diverge again. Evidence behavior is preserved exactly.

Scope guard honored: no change to plan.go's CheckApprovalLock (it correctly hashes whatever TasksPath it is handed) or to ActivatePlan / OutDir wiring. The defect was solely managedPRSources assuming one layout.

Conformance tests (root up)

  • TestFeatureArtifactPathResolvesBothLayouts — table-driven unit test of the resolution rule itself: only-compiled → compiled; only-root → root; both → canonical; neither → last candidate.
  • TestManagedPRSourcesAcceptsBothTaskGraphLayouts — table-driven integration over {compiled, feature-root}; the feature-root case asserts the fixture is genuinely the old layout (root tasks.json, no compiled/) and that managedPRSources succeeds (lock's task_graph hash matches the resolved root file). Existing compiled-layout managed-PR tests stay green.

Refactored the existing activateManagedFeature helper into activateManagedFeatureLayout(t, repo, feature, compiled bool); the old signature remains as a thin wrapper so every existing caller is unchanged.

Verification

From product-engineering-loop: go build ./..., go vet ./..., go test ./... all pass (new unit + integration cases plus the full existing suite, including config_documentation_test.go — no doc drift, so no release note required).

managedPRSources hardcoded <feature>/compiled/tasks.json with no
fallback and handed it to CheckApprovalLock, which hashes whatever
TasksPath it is given. Features whose plan.lock.json was written in the
older feature-root layout (tasks.json at the feature root, no compiled/
dir) have no compiled/tasks.json, so SHA256File fails, the task_graph
label mismatches, and managed PR preparation reports "requires a current
build lock" — blocking the ship-gate even though build/test/review all
passed.

Introduce one shared featureArtifactPath resolver (canonical location
first, alternate as fallback) and route both the task graph (compiled
canonical) and evidence (root canonical) through it, so the two layout
resolutions can never silently diverge again. No change to
CheckApprovalLock or ActivatePlan/OutDir wiring.

Adds a table-driven unit test of the resolver and a table-driven managed
PR integration test over both {compiled, feature-root} layouts.
… guard

CI's 'Generated distribution' check (scripts/release_notes.py check-policy)
blocks any PR that touches labs/12-product-engineering-loop without adding a
new release note. That check is not part of go test, so a green local test
run hides it and costs a fail/push/re-PR round trip.

Add AGENTS.md in product-engineering-loop documenting the always-required
release note, the fragment contract, and the local preflight command that
mirrors CI. Also add the missing release note for the task-graph layout fix.
@bigboateng

Copy link
Copy Markdown
Contributor Author

Correction: this lab change does require a release note (CI's Generated distribution gate, not part of go test). Added boatstack-distribution/release-notes/2026-07-23-managed-pr-task-graph-layout.md, plus an AGENTS.md in product-engineering-loop documenting the always-required note and the local release_notes.py preflight command so future PRs catch this before CI.

@bigboateng
bigboateng merged commit fe5ded4 into main Jul 23, 2026
5 checks passed
@bigboateng
bigboateng deleted the boatstack/fix-tasks-layout-fallback branch July 23, 2026 16:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant