Skip to content

feat(orchestrate): move the bundled fleet into fleet.json - #586

Merged
Tryanks merged 1 commit into
mainfrom
feat/orchestrate-fleet-manifest
Oct 4, 2026
Merged

Tryanks merged 1 commit into
mainfrom
feat/orchestrate-fleet-manifest

Conversation

@Tryanks

@Tryanks Tryanks commented Oct 4, 2026 •

Copy link
Copy Markdown
Owner

Summary

Orchestrate's bundled fleet (which models, their role, their guidance, the pre-discovery effort lists) moves from Rust constants into one data file parsed once in tcode-core. This is bundled data, not a plugin manifest: no loading, permission or host-API concepts.

 assets/orchestrate/
-├── astra.md
-├── fable-5-1.md
+├── fleet.json                       # models, roles, guidance, effort lists
 ├── workflow.md                      # unchanged
 └── collaboration.md                 # unchanged
 crates/core/src/settings/
+├── orchestrate_fleet.rs             # parse fleet.json once
+└── orchestrate_legacy.rs            # closed set of FNV-1a fingerprints of old bundled texts

Settings store overrides only.

OrchestrateChildModel::guidance
  if description is empty  → bundled guidance for this role and model
  else                     → the user's text
on patch
  if text == bundled guidance → normalize back to empty   # bundled prose never hits disk again
untouched row on the built-in endpoint
  carries bundled: <profile id> and follows that profile's model on load

One last migration. Every guidance text that older versions persisted as a bundled default is recognized by a frozen fingerprint set and collapsed to empty. The set is closed.

Behaviour changes for existing users

  • A changed enabled / fast switch no longer pins an untouched row to its superseded model; it moves to the successor and keeps its switches.
  • An untouched claude-opus-5 row merges into an existing claude-opus-5-5 row instead of sitting beside it.
  • claude-opus-5 no longer has bundled guidance (main reused Opus 5.5's text for it).
  • Clearing a description on a bundled model restores the bundled guidance; a bundled model can no longer be given "no guidance".
  • Rows with an endpoint profile never track a bundled profile, so they do not follow model swaps.

Evidence

  • Before / after prompt output: with default settings, render_orchestrate_configuration, compose_collaboration_brief and compose_orchestrate_text are byte-identical to main (40,017 bytes compared with cmp via a throwaway test, not committed).
  • Tests: five migration tests kept with inputs rewritten as literal old-file JSON and assertions on the resulting fleet rather than stored text. Two deleted, their contract covered by orchestrate_recognizes_every_persisted_bundled_text, which is driven by the 18 texts extracted from main into tests/fixtures/orchestrate/persisted_bundled_texts.json. Added: rows store bundled guidance by reference; tracking rows follow their bundled profile.
  • App: Settings → Orchestrate in a throwaway profile: default rows show bundled guidance, an edit persists across restart, restore returns the bundled text and the orchestrate section disappears from settings.json, add/remove works, an old-format file migrates. Light theme, one width; layout unchanged.
cargo fmt / clippy -D warnings / machete         ✓
cargo nextest run --workspace --locked           887 passed
Web / iOS / Android checks                       ✓

Not exercised: a live dispatch or collaboration against a provider.

Merge Danger

Door: one-way for settings on disk

Once a user's settings.json is normalized (bundled text collapsed to empty, bundled: markers added), an older build reads those empty descriptions as "no guidance". The fingerprint set is frozen, so texts persisted by this build cannot be re-recognized later.

Blast Radius: orchestrate-settings

PROTOCOL_VERSION 8 → 9; an older peer would see empty guidance. The behaviour changes above alter which model an untouched row lands on after an upgrade.

The bundled collaboration and execution profiles, their guidance and the
pre-discovery effort lists move from Rust constants into
`assets/orchestrate/fleet.json`, parsed once in tcode-core. `astra.md` and
`fable-5-1.md` are folded into it.

Settings now store overrides only: an empty description means the bundled
guidance for the row's role and model, resolved by
`OrchestrateChildModel::guidance`, which prompt rendering and the settings
UI share. An untouched row on the built-in endpoint carries the id of the
bundled profile it tracks (`bundled`) and takes that profile's model on
load, so a later bundle swap needs no text comparison. Normalization in
core maintains the marker and turns text equal to the bundled guidance
back into an empty description.

Files from older versions migrate once, in `orchestrate_legacy`: rows
holding any guidance text ever persisted as a bundled default (a frozen
set of fingerprints, closed now that bundled text is never written) become
tracking rows of the profile that superseded them. Two outcomes change: a
changed enabled/fast switch no longer keeps such a row on its old model,
and an untouched Opus 5 row merges into an existing Opus 5.5 row.

Rendered prompts are unchanged for default settings. PROTOCOL_VERSION
becomes 9: an older peer would read the empty descriptions as no guidance.
@Tryanks
Tryanks merged commit 7da00bc into main Oct 4, 2026
7 checks passed
@Tryanks
Tryanks deleted the feat/orchestrate-fleet-manifest branch October 4, 2026 12:22
@Tryanks Tryanks changed the title feat(orchestrate): ship the bundled fleet as a data manifest feat(orchestrate): move the bundled fleet into fleet.json Oct 6, 2026
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