Skip to content

Separate host admission from projection selection - #225

Merged
bigboateng merged 6 commits into
mainfrom
feat/host-projection-selection
Aug 17, 2026
Merged

Separate host admission from projection selection#225
bigboateng merged 6 commits into
mainfrom
feat/host-projection-selection

Conversation

@bigboateng

Copy link
Copy Markdown
Contributor

Summary

  • separate runtime hosts from explicit repository projections in strict project configuration schema 4
  • add the shared non-kernel internal/hostprojection model, canonical SHA-256 selection fingerprint, four host-native layouts, and strict path validation
  • replace the legacy skill contracts with GenerateProjections, GeneratedProjections, ProjectedHostProjectionFiles, and .boatstack/host-projections.json
  • bind projection selection and exact generated hashes through artifact schema 4, ownership schema 2, manifest schema 2, and compiler 6 without changing Control Program semantics
  • publish generated files, shared checkout metadata, ownership, and the artifact through one serialized rollback-capable transaction, with exact guarded retirement and the artifact last
  • derive maintenance projections from exact configuration input while leaving supervisor runtime admission dependent only on hosts
  • bind exact Flow and maintenance projection membership/removals into control bundles

Breaking impact

Existing repositories must add an explicit projections array, apply it through configuration.mutate, compile and check every Flow while product work remains suspended, then run the normal installation update before resuming. Missing/null, duplicate, unsupported, and non-subset selections fail closed; explicit [] is valid.

Verification

  • npm run test:flow-sdk
  • npm run docs:check
  • python3 .github/scripts/run_go_tests.py --jobs 2 — 533/533 tests passed
  • python3 -m unittest discover -s .github/tests -p 'test_*.py' -v — 55 passed, 1 expected failure
  • go test -race ./...
  • go vet ./...
  • go build ./...
  • GOOS=windows GOARCH=amd64 go build ./...
  • bash -n install.sh
  • release-note validate/preflight and git diff --check

The default ten-worker local Go controller was also exercised; four existing subprocess deadline tests exceeded their 30-second bound under host contention. The complete suite passed at two isolated workers, and those four tests passed together immediately in 1.331 seconds.

Consumer proof

An independent clean bigboateng/boatstack-test clone at base 1d678acb5502d5c1dd7b8fe8c1366cde87d637c3 used the exact candidate helper and locally packed TypeScript packages:

  • A: hosts=cli,codex,cursor, projections=codex proved Cursor runtime admission without Cursor generated files and reached a fresh Codex Product Delivery delegation boundary.
  • B: all four hosts/projections produced every canonical path, retained the Flow ProgramFingerprint, changed configuration/control-bundle fingerprints, and passed Flow checks.
  • C: returning to Codex-only retired exact Claude/Cursor/Gemini outputs, preserved sentinels and host directories, passed Flow check, and reached a fresh Codex run.

Consumer worktree: /private/tmp/boatstack-test-host-projection-selection-final (left clean; no consumer PR).

Locus

Locus validated a hash-bound model of commit 6a1609e121a53e86a3bc63ae52563bcf54a5a98c as faithful and found no modeled forbidden path (res-719fc5602029edb5b8ed6b1ade0e14988c39f48f9e2361e521d219e7ac0c29b1). The bounded inventory classifies 12 modeled admission/generation/publication/retirement sites and three non-mutating exclusions; event-completeness is fully discharged with path/line evidence and refusing tests.

The system claim remains advisory: Locus additionally requires Git-revision lineage for every evidence reference, while the inventory receipt is intentionally scratch-held. The verified-target frontier therefore reports blocked with no remaining implementation action. One oversized Observatory spool was retained locally after a 413; subsequent final runs archived successfully.

@cursor

cursor Bot commented Aug 17, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codex automated review

Verdict: patch is incorrect
Confidence: 0.99

The new projection model is internally consistent for fresh repositories, but two strict version changes make the stated existing-repository migration path unreachable. Model-level verification is not recommended before merge; deterministic cross-version fixtures using the actual base binary should first cover configuration, manifest, artifact, and ownership migration.

Findings without inline diff anchors

[P1] Provide a governed bridge from configuration schema 3

Invariant: an installed repository must retain an admitted transition that can establish the next version's required configuration and control-bundle files. A base-revision installation has schema-3 project.json, runtime.json, and host-skills.json; the old runtime rejects a schema-4 mutation candidate, while the head runtime rejects the durable schema-3 file here before configuration.mutate or installation.update can run. The new source-bundle check also requires host-projections.json before the update that would create it. Thus the documented migration sequence cannot start, leaving existing repositories unable to upgrade without an out-of-band rewrite or reinstall. A regression test should install with the actual base binary, then use the head candidate to govern the schema change and update successfully, including conversion of the legacy manifest.

Confidence: 0.99

Location: boatstack/internal/softwaredelivery/protocol/config.go:159-160 (RIGHT)


[P1] Migrate existing Flow projection ownership records

Invariant: prior kernel-owned provenance must remain readable until it has safely authorized its replacement. A Flow compiled by the base revision leaves a schema-1 ownership record containing generated_skills; head flow compile loads that record into the new schema-2 structure, and the strict decoder/schema check rejects it before any projection or artifact can be replaced. Since head also rejects the old compiler-5 artifact, recompilation—the intended migration path—is deterministically blocked for every previously compiled Flow. The observable result is that existing Flows cannot be recompiled or resumed without deleting authority metadata manually. A regression test should compile a Flow with the actual base binary, then compile it with head and verify atomic conversion to schema 2 plus safe retirement of the old generated files.

Confidence: 0.99

Location: boatstack/internal/runtime/flow_ownership.go:207-218 (RIGHT)

@bigboateng

Copy link
Copy Markdown
Contributor Author

Review cycle 1 disposition (exact head 6a1609e121a53e86a3bc63ae52563bcf54a5a98c):

Both reported P1s require compatibility readers/migration for schema-3 configuration, host-skills.json, compiler-5 artifacts, or schema-1 generated_skills ownership. This PR intentionally does not add those paths: the accepted contract is a complete breaking replacement that removes legacy aliases/readers and host-derived defaults. The documented governed sequence is the supported sequence once schema 4 is admitted; it is not a promise that a schema-3 installation can self-migrate in place.

No code change was made for these findings because it would violate the breaking boundary. Verification after disposition:

  • strict old-schema rejection: TestProjectConfigurationIsStrictAndVersioned
  • forged/old ownership refusal: TestFlowCompileRejectsForgedArtifactOwnership
  • exact retirement: TestFlowCompileRetiresOnlyUnmodifiedPriorGeneratedProjections
  • shared final-owner protection: TestSharedCheckoutMetadataRetiresOnlyAfterFinalFlowOwner
  • prohibited legacy identifiers remain absent outside historical release notes
  • worktree remains clean at the reviewed head

The lack of in-place v3/v1 migration is a deliberate release boundary and should remain visible in review rather than being silently reintroduced as compatibility behavior.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codex automated review

Verdict: patch is incorrect
Confidence: 0.98

The patch introduces a blocked base-to-head upgrade, a shared-projection TOCTOU race, and two completeness regressions. Model-level verification is recommended before merge, focused on whether projection-selection changes can interleave with Flow publication or retirement into any other manifest/ownership mismatch.

Comment on lines +181 to 182
manifestPath := filepath.Join(repository, ".boatstack", "host-projections.json")
manifestRaw, manifestExists, _, err := readAllIfExists(manifestPath)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] Preserve a governed upgrade path for legacy projection manifests

Invariant: a repository installed by the base revision must be able to reach the new admitted projection format through the documented governed update path. A base installation has .boatstack/host-skills.json and generated boatstack-update files; the head reads only .boatstack/host-projections.json, treats the existing generated files as unmanaged, and configuration.mutate refuses with an unmanaged collision. The schema-3 configuration is also rejected before update admission, so there is no head transition that can migrate the legacy ownership. Existing repositories cannot update without manually deleting or rewriting kernel-owned state. A regression test should initialize with the base binary, then use the head binary to govern a schema-4 projection change and update successfully while preserving exact legacy ownership.

Confidence: 0.98

Comment on lines +240 to +241
if hostprojection.IsSharedCheckoutPath(relative) {
referenced, referenceErr := boatstackruntime.SharedFlowProjectionReferenced(repository, relative, prior.Files[relative])

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] Serialize shared-projection reference checks with configuration mutation

Invariant: a committed projection-selection transition must not remove a file referenced by a concurrently committed Flow ownership record. configuration.mutate can observe no Flow reference here and prepare deletion of a shared Cursor/Gemini .gitattributes; before its mutations execute, flow compile can acquire the projection lease and commit that file plus a new ownership record. The configuration transaction does not acquire that lease, so it then deletes the now-referenced file and commits successfully, leaving the Flow artifact and ownership record bound to an absent output; subsequent checks fail, and recompilation cannot recreate it because provenance expects an existing prior hash. This race is introduced by sharing these paths across maintenance and Flow projections. A regression test should pause configuration mutation after this reference check, compile the first Flow owner, resume the mutation, and assert that either the mutation retries/refuses or the shared file remains.

Confidence: 0.95

Comment on lines +31 to +33
paths, err := hostprojection.FlowPaths(projection, slug)
if err != nil {
return nil, err

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Encode all valid control-program IDs into projection slugs

Invariant: every Control Program accepted by the IR ABI must remain projectable for a selected supported host. The ABI permits . and _ in program and entry IDs, but flowSkillSlug leaves those characters unchanged and FlowPaths now accepts only alphanumeric/hyphen slugs. Thus a valid program such as product.delivery with entry run, or program product with entry run_now, compiles normally but GenerateProjections deterministically returns FLOW_PROJECTION_PATH_INVALID, preventing boatstack flow compile. The new path validator introduces this rejection; previously these IDs produced projections. Add a regression test projecting valid dot/underscore IDs for each host and assert collision-free encoded paths are generated.

Confidence: 0.99

Comment on lines +543 to +545
size, parseErr := strconv.ParseInt(fields[2], 10, 64)
if parseErr != nil || size < 0 || size > 64<<20 {
return fmt.Errorf("CONTROL_BUNDLE_STALE: revision %s has invalid size for %s", revision, file.Path)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Do not reject exact committed bundle files solely above 64 MiB

Invariant: any control bundle accepted at the repository root must also verify at an exact revision containing identical bytes. Snapshot construction and root verification impose no 64 MiB limit, so a valid large dependency lock or other bound file can be hashed and committed; workspace.cut then calls revision verification, which rejects that identical blob as an invalid size. This patch adds the asymmetric cap and makes such repositories unable to create a managed workspace. A regression test should commit a 64 MiB-plus-one bound file, verify the root snapshot, and require VerifyControlBundleRevision to accept the exact commit (or enforce the same documented limit when constructing the snapshot).

Confidence: 0.98

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codex automated review

Verdict: patch is incorrect
Confidence: 0.98

The patch blocks the advertised base-to-head upgrade path and introduces a control-bundle verifier that rejects snapshots accepted by admission. Model-level verification is recommended after these fixes, especially for progress across projection-selection changes and shared projection retirement.

Comment thread boatstack/internal/softwaredelivery/protocol/config.go
Comment thread boatstack/internal/runtime/control_bundle.go
@bigboateng

bigboateng commented Aug 17, 2026

Copy link
Copy Markdown
Contributor Author

Review cycle 1 settled at head d6f5f35 (reviewed head b22f564).

  • Schema-3 migration: unsupported by the accepted flag-day alpha contract and explicitly confirmed out of scope by the user; no compatibility reader or migration shim was added. Its evidence reply closes the finding as inapplicable to this breaking PR, and the thread is resolved.
  • Control-bundle size asymmetry: fixed with one 64 MiB admission and verification boundary across snapshot creation, replacement, working-tree verification, and exact-revision verification. The repaired thread is resolved.

Public verification: TestProjectConfigurationIsStrictAndVersioned; TestControlBundleSizeLimitIsConsistentAcrossAdmissionAndVerification; full internal/runtime tests; full internal/runtime race tests; dependent boatstack-helper control-bundle tests; go vet ./internal/runtime; git diff --check.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codex automated review

Verdict: patch is incorrect
Confidence: 0.98

The new projection behavior is internally coherent for fresh schema-4 repositories, but the strict, simultaneous persistent-format changes make the advertised existing-repository update path unreachable. Model-level verification is not recommended before merge; this is a deterministic compatibility failure best covered by a real base-to-head upgrade test.

Findings without inline diff anchors

[P1] Schema 4 leaves existing installations with no governed upgrade path

Invariant: an installed repository must remain able to reach its update transition through kernel-owned state changes. Minimal sequence: initialize with the base revision (schema-3 project config, schema-1 host-skill manifest, schema-3 Flow artifacts) → run the head installer in update mode → the head runtime loads the current control bundle → Validate rejects schema 3 before resolution or effects. The base runtime also rejects a schema-4 configuration candidate, while the head subsequently rejects the old manifest, artifact, and ownership schemas, so retrying or following the documented add/configure/recompile/update sequence cannot progress. This patch introduces all of these strict schema bumps without a transition that migrates them, making existing repositories unupgradable except through out-of-band deletion/reconstruction of kernel-managed state. The smallest regression test should initialize a repository using an actual base-revision binary, then run the head update path and verify a governed migration completes and the head runtime can load the resulting repository.

Confidence: 0.98

Location: boatstack/internal/softwaredelivery/protocol/config.go:159-160 (RIGHT)

@bigboateng

Copy link
Copy Markdown
Contributor Author

Review cycle 1 (configured three-cycle run) settled at exact head d6f5f35.

The sole P1 asks for schema-3 and legacy-state migration. It is unsupported by the accepted flag-day alpha contract, and the user explicitly confirmed that breaking changes do not need compatibility repair. No compatibility reader, alias, or migration shim was added. The exact-head refusing test TestProjectConfigurationIsStrictAndVersioned passes; all 18 exact-head checks pass. There were no inline comments in this batch.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codex automated review

Verdict: patch is incorrect
Confidence: 0.98

The new projection model is internally well-bound for fresh repositories, but the patch lacks a reachable governed migration from the stated base and introduces an unlocked ownership/deletion race. Model-level verification is not recommended before merge; real base/head migration and deterministic concurrency tests are the appropriate closure oracles.

Findings without inline diff anchors

[P1] Provide a governed upgrade path from schema 3

Invariant: an installed base-revision repository must be able to reach the new admitted formats without first mutating kernel-owned state outside Boatstack. A base installation has schema-3 project configuration, artifact/ownership schema 3/1, and .boatstack/host-skills.json; invoking the head update rejects the current config here before resolution. The old runtime also rejects a schema-4 candidate, while the head compiler rejects old ownership records and the new projection writer treats legacy generated files as unmanaged collisions. Thus the documented add-projections → recompile → update sequence is unreachable and existing repositories cannot upgrade without manually deleting or rewriting governed files. Add an actual base-to-head fixture that installs with the base binary and upgrades with the head binary, asserting committed configuration and installation receipts plus migrated manifests/ownership.

Confidence: 0.99

Location: boatstack/internal/softwaredelivery/protocol/config.go:159-160 (RIGHT)

Comment thread boatstack/internal/softwaredelivery/effects/host_projections.go

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codex automated review

Verdict: patch is incorrect
Confidence: 0.98

The patch introduces an upgrade dead end for existing Flow ownership records and rejects valid ControlProgram identities during projection generation. Model-level verification is recommended before merge, particularly to check whether any mixed ownership/manifest version or shared-file retirement interleaving can become blocking or lose its recovery path.

Comment thread boatstack/internal/runtime/flow_ownership.go
Comment thread boatstack/internal/hostprojection/projection.go
@bigboateng

Copy link
Copy Markdown
Contributor Author

Review cycle 2 settled at exact head a4b92a4f1dcdbd34fc5e9885934981c15b5f841b.

  • P1 schema-3 upgrade path: unsupported for this PR. The accepted contract is an intentional flag-day alpha replacement with no compatibility readers or legacy migration aliases; schema 3 remains fail-closed by design.
  • P2 shared projection retirement race: fixed by making configuration and installation resource locks hold the existing Flow projection lease across final preparation, execution, and verification. TestConfigurationLockSerializesSharedProjectionPublicationAcrossPreparation proves concurrent ownership publication cannot cross that boundary and leaves no partial metadata or ownership.

Public verification: go test ./internal/softwaredelivery/effects; go test ./cmd/boatstack-helper; the focused race-detector regression; and all 18 exact-head PR checks across Linux, macOS, and Windows.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codex automated review

Verdict: patch is incorrect
Confidence: 0.97

The patch can overwrite unowned shared host metadata and can commit an installation target whose Flow artifacts contradict its configuration. Model-level verification is recommended before merge: verify shared-owner retirement across maintenance/Flow selection changes and that every initialization target is semantically reconstructible.

Findings without inline diff anchors

[P1] Validate initialization artifacts against the candidate projection selection

Invariant: a successfully committed installation target must be semantically reconstructible from its project configuration and Flow artifacts. Start with fresh durable state but an existing valid project using projection set A and Flow artifacts compiled for A, then run installation.initialize with candidate config B. The source snapshot validates against A; this code replaces only project and maintenance-projection files, retains the A-bound artifacts, and commits that mixed snapshot as the target. Hash verification succeeds, but the next normal bundle build deterministically fails with FLOW_PROJECTION_SELECTION_STALE. This mismatch is introduced because artifacts now bind projection selection while initialization target construction does not revalidate them. The result is a successful installation receipt followed by a repository that cannot operate until an out-of-band recompile. A regression test should initialize an A-compiled repository with candidate B and require refusal with zero effects. The target must either validate every artifact against B or reject the selection change before applying.

Confidence: 0.96

Location: boatstack/cmd/boatstack-helper/control_bundle.go:328-332 (RIGHT)

Comment thread boatstack/internal/softwaredelivery/effects/host_projections.go
@bigboateng

Copy link
Copy Markdown
Contributor Author

Review cycle 3 settled at exact head 7bcd6fd3b54868cde7cfc2c1dc6dc83b53064f18.

  • P1 schema-1 Flow ownership migration: unsupported under the explicitly accepted flag-day breaking contract; no generated_skills compatibility reader or migration shim was added.
  • P2 semantic-ID projection paths: fixed with injective component encoding for ., _, ambiguous entry -, and the reserved x0 prefix while preserving ordinary readable slugs. TestGeneratedProjectionSlugsEncodeEveryValidSemanticSeparator verifies all four hosts, valid paths, and collision freedom.

Public verification: full Flow and ControlProgram suites, focused projection/host-path suites, race-enabled Flow projection tests, vet, git diff --check, and all 18 exact-head PR checks across Linux, macOS, and Windows.

@bigboateng

bigboateng commented Aug 17, 2026

Copy link
Copy Markdown
Contributor Author

Post-cycle-3 P1 settlement at exact head b0167b9d2325b309a0ade4e26fb09f1910763dfb:

  • Shared checkout metadata ownership: fixed with per-path provenance checks. Equal-byte unowned Cursor/Gemini .gitattributes files are refused; exact Flow-owned shared bytes remain reference-countable. The inline thread is resolved.
  • Initialization target consistency: fixed by validating every retained Flow artifact with the canonical artifact checker against the candidate project configuration projection selection before constructing an installation target. A selection-A repository presented with candidate selection B is refused before any project or maintenance state changes.

Verification: full go test ./...; full go vet ./...; full go build ./...; focused race tests; git diff --check; and faithful Locus pre/post models for both findings, with no post-fix path to either forbidden state. The previously reviewed schema-compatibility findings remain intentionally unsupported under the approved flag-day breaking contract.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codex automated review

Verdict: patch is incorrect
Confidence: 0.98

The patch introduces a deterministic self-lock in a reachable recovery transition and leaves the stated existing-repository upgrade procedure with no executable bridge across its persisted schema changes. Model-level verification is recommended for all recovery transitions that acquire the new projection lease, particularly to confirm each lease is acquired exactly once and retains a progress path.

Findings without inline diff anchors

[P1] Provide a reachable upgrade path from the persisted schema-3 formats

Invariant: an advertised upgrade sequence must have an authorized operation that can read the old durable formats and commit their replacements. Starting with a repository produced by the base revision (project.json schema 3, artifact schema 3, ownership schema 1), the head candidate rejects the current config while building the source control bundle, so installation.update cannot run. The old runtime also rejects a schema-4 configuration.mutate; even after an unmanaged config edit, strict schema-2 ownership decoding prevents the documented Flow recompilation and artifact schema 3 is rejected. Thus existing repositories cannot perform the release-note sequence or obtain an update receipt without manually deleting/resetting control state. This is introduced by bumping all formats while retaining only current-version decoders. The regression should create the repository with the actual base binary, then exercise the documented configuration change, Flow recompilation, and installation update with the head binary while asserting preserved state and a committed update receipt.

Confidence: 0.96

Location: boatstack/internal/softwaredelivery/protocol/config.go:159-160 (RIGHT)

Comment on lines +559 to +560
case "configuration.initialize", "configuration.mutate", "installation.initialize", "installation.update", "installation.reconcile-update":
return true

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] Include configuration reconciliation in maintenance lease ownership

Invariant: a prescribed recovery transition must not deterministically contend with a lease already held by its own invocation. A repository Flow can expose configuration.reconcile; when configuration recovery is required, apply first acquires the Flow projection lease here because this transition is absent from the exemption list. The engine then acquires its configuration resource lock, whose patched locker attempts to acquire the same non-reentrant projection lease and returns FLOW_PROJECTION_BUSY. State remains unchanged and every retry repeats the refusal, making configuration recovery unreachable for that Flow. Add a production-path regression test that prescribes and applies configuration.reconcile through a repository Flow and requires a committed receipt.

Confidence: 0.99

@bigboateng
bigboateng merged commit d3404c1 into main Aug 17, 2026
18 checks passed
@bigboateng
bigboateng deleted the feat/host-projection-selection branch August 17, 2026 09:00
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