fix(templates): stop shipping the dd-* demo fleet and a dead GitHub repo list as starting points - #1934
Conversation
|
Resolve by running |
AndriiPasternak31
left a comment
There was a problem hiding this comment.
APPROVE — /review + /validate-pr. Zero critical findings, 3 warnings, none blocking.
I verified the load-bearing claims from source rather than from the PR body, and mutation-tested the guards. Everything holds. One correction below, in the PR's favour.
Verified independently
| Claim | Method | Result |
|---|---|---|
.gitleaks.toml is a regexes entry, not paths |
read the full [[allowlists]] block; grepped every +/- line |
✅ '''YOUR_TOKEN''' appended to regexes (:65); paths (:50-61) byte-untouched, so config/manifests/ stays scanned for real secrets. The only added lines naming config/manifests are comment text inside the regexes entry. gitleaks CI passing is the empirical half. |
vc-due-diligence.yaml is inert |
grepped every config/manifests reference repo-wide; read _resolve_manifest |
✅ BUNDLED_MANIFEST_PATH (system_seed_service.py:83) is a string literal; the resolver reads exactly two sources (env override + that literal). Zero glob/iterdir/listdir/scandir in the three system modules. Every other reference is packaging (Dockerfile COPY, compose :ro). |
hidden: is catalog-only — the fleet stays deployable |
traced all read paths | ✅ get_local_templates() (:529) is the sole exclusion point. get_local_template(), crud._resolve_local_template(), and system_service._preflight_template all resolve by directory name and never read the flag. |
| Manifest's name/roster claims | read the cited code | ✅ base_name = f"{system_name}-{short_name}" (system_service.py:383). dd-lead/CLAUDE.md = 13 occurrences, 9 distinct names — exactly the 9 permissions.explicit edges, dd-intake correctly absent. The other ten dd-*/CLAUDE.md: 0 cross-agent refs, so 9 edges is the complete topology, not an omission. |
explicit = full replacement |
read configure_permissions |
✅ :455-459 clears every system agent absent from the map before applying. Comment is accurate. |
| Catalog outcome | audited all 25 dirs on disk | ✅ VISIBLE = {sage, scout, scribe}, 22 hidden, 0 undeclared — matches the PR's table exactly. |
| Tests | ran them | ✅ 69 passed, reproducing the stated number. |
| Guards aren't vacuous | mutated the tree, ran, restored | ✅ Drop dd-founder's hidden: → 3 red. Manifest name: → vc-demo → roster red. Both match the mutation table. Tree restored, 69 green again, git status clean. |
| Test hygiene | ran tests/lint_sys_modules.py |
✅ 194 violations vs baseline 240 — no new. |
Two things the PR under-claims, worth stating: Invariant #13 needed no code change — MCP list_templates → client.listTemplates() → GET /api/templates → the same single filter, so all three surfaces converge (only the tool description needed editing, which it got). And the upgrade path is fine — both compose files bind-mount ./config/agent-templates:/agent-configs/templates:ro, so existing installs pick up the hidden: flags on restart rather than needing a volume reset.
The new empty state's CTA is real, not decorative: useTemplate({id:'github-custom'}) → :initial-template → form.template (CreateAgentModal.vue:347), and :447 explicitly exempts the sentinel from the "template doesn't exist → reset to blank" guard, with :365 auto-focusing the repo input.
Correction: the merge-order table over-warns
I simulated squash-merges in a throwaway worktree rather than predicting from hunk overlap:
| Scenario | Conflicts |
|---|---|
dev + #1935, rebase #1934 |
docs/memory/requirements/core-agent.md only |
dev + #1935 + #1936, rebase #1934 |
docs/memory/requirements/core-agent.md only |
template-processing.md auto-merges; feature-flows.md and test_local_templates_listing.py never conflict. The one conflict is a pure adjacent-insert — #1935's #1900 read-path bullet vs this PR's two bullets at the same §4.1 anchor, zero semantic overlap. Resolution is keep both, either order. I resolved it that way, completed all 7 commits clean, and re-ran: 84 passed (this PR's 69 + #1935's additions to the same files). The two PRs' guards coexist, and #1935's own bullet independently states "Hidden templates (hidden: true) stay resolvable by id: the barrier reads the name, never the flag" — corroborating this PR's central claim.
Flagging this down because an inflated conflict list invites a careless bulk resolution on the one file that actually needs care.
Warnings (non-blocking)
-
The superseded demo manifest keeps its live footgun.
docs/demos/vc-due-diligence/system-manifest.yaml:46still carriesprompt:, andsystem_service.py:1143writes it fleet-wide viadb.set_setting("trinity_prompt", …). TheSUPERSEDEDheader names the hazard and the README is repointed — real mitigation — but the header itself says the file "is NOT guarded against drift," and removal is one line. Its sibling claims do check out:auto_starthas zero reads, and the onlyfoldersread is per-agent (:193). Fine as the filed follow-up; noting the one-line option. -
#1936's prose goes stale on rebase. Its §4.1.1 says "all 14 visible bundled templates failed the same four HARD checks" — after this PR, 3 are visible, contradicting §4.1 two bullets above. Its tests are safe (
GUARDED_TEMPLATESis an explicit tuple, deliberately not a livehiddenquery, with a comment citing #1931). Docs-coherence fix for whoever lands second. -
Issue #1931 carries both
status-in-progressandstatus-ready. Auto-promotion writesstatus-in-devand leavesstatus-readyas drift. Worth dropping before merge.
Suggestions
requirements/security.md§20.8 doesn't name the newYOUR_TOKENentry. Consistent with precedent (it never listedyour-api-key/your-domain\.comeither), so optional.test_1931_manifest_roster.pymutatessys.pathat import while its sibling explicitly argues against that, and itsassert pathsruns at collection time (called in the@parametrizeat:72) so a missingconfig/manifests/errors rather than skips. Cosmetic.
Forward-looking
Once #1911 (ent#126) lands, GET /api/systems/manifests globs config/manifests/ and surfaces each manifest as a one-click UI install with a sets_prompt warning — so vc-due-diligence.yaml stops being merely inert data and becomes a listed, installable catalog entry. That reads as AC #2's ideal fulfilment rather than a defect, and I checked the interaction: _preflight_template resolves through _resolve_local_template, which ignores hidden, so all 11 dd-* preflight valid: true rather than showing up broken. No action — just don't carry "inert" forward as an assumption after #1911.
Process
All 24 CI checks pass, including gitleaks, prod-image-smoke, regression diff, the sys.modules lint, e2e, and 6 pytest runs (3 seeds × base/head). Security greps clean — the only "email" hit is @pytest.mark.parametrize and the 5 "IP" hits are GitHub-logo SVG path coordinates. Zero new os.getenv() (no config-packaging gap); config.py is a modification already covered by Dockerfile:83, and the new manifest ships via the wholesale Dockerfile:109 COPY ../../config/manifests. architecture.md:222 names only default-system.yaml for the seed and stays accurate with a second manifest present, so skipping it was right. All 6 ACs trace to a named guard.
The detail I'd single out: test_real_catalog_surfaces_the_three_starters noticed its own ordering clause could only go vacuous, not red, on the very change it guarded — said so in the docstring, and replaced it with a non-vacuous priority == 20 assertion. That's the failure mode most PRs ship silently.
Merge order: land #1935 first, expect exactly one conflict in core-agent.md, resolve keep-both.
…ange (#1931) Rule #1: land the requirements/flow delta before the code. requirements/core-agent.md - §4.1: two bullets — catalog intent is DECLARED, not defaulted (every bundled directory must set `hidden:`; the runtime default is deliberately unchanged, because flipping it turns a forgotten key into a silent absence); and demo fleets ship hidden but stay deployable via a bundled manifest, with the system-name/short-name coupling to dd-lead's hardcoded roster spelled out. - §4.2.1: the shipped GitHub default list is empty and why; None-vs-[] now differ only in the `source` badge; `github:owner/repo` create is untouched. - §4.5: the GitHub-zero empty state — marketplace-first, then the owner/repo CTA, then the role-branched curation hint; plus the precedence rule that makes it mutually exclusive with the page-level empty state. feature-flows - library-page.md: the GitHub-zero placeholder, the 4-row precedence truth table, and a #1931 revision-history row. - template-processing.md: the sort no longer "orders starters ahead of the rest" — after this change there is no rest; component is Library.vue. - mcp-orchestration.md: drop the agent-ruby example that will never again appear in list_templates. No architecture.md change: it documents the mechanism (the `hidden:` filter, the None-vs-[] fallback, the section render), and no mechanism changes here. Adding a catalog-contents paragraph would give requirements/core-agent.md §4 a second home, against that file's own editorial rule #1. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ult list (#1931) A fresh install's Library showed 14 local templates — 11 of them the VC due-diligence demo fleet — plus 6 GitHub repos last pushed Dec-2025/Jan-2026 that no install had ever overridden. The visible catalog is now the 3 starters we actually stand behind. get_local_templates() on the real catalog: 14 -> 3 (sage, scout, scribe) GitHub entries on a default install: 6 -> 0 bundled dirs omitting `hidden:`: 14 -> 0 bundled dirs total: 25 -> 25 (nothing deleted) Catalog - 11 x `hidden: true` on dd-*/template.yaml, placed and commented to match the 11 directories that already declare it. Not deleted, not moved: it is a demo we still run, `local:dd-lead` stays creatable by id, and the resolver never reads `hidden` (verified: get_local_template("local:dd-lead") still resolves). - 3 x `hidden: false` on sage/scout/scribe — the AC asks a new directory to DECLARE its catalog intent, so the declaration has to be mandatory. - DEFAULT_GITHUB_TEMPLATE_REPOS = []. Every consumer already tolerates it (five existing unit tests stub exactly this), and the one path that could have regressed does not: recreating an agent made from `github:abilityai/agent-ruby` routes through get_github_template, whose `if repo in DEFAULT_...` branch and "Dynamic" fallback are byte-identical two-line bodies. Zero behavioural delta. Emptying a BROWSE list deletes no data and stops no agent, so the #1638 "mutable code default read at action time" lesson does not bite here. Side-effect, intended: GET /api/templates now makes zero outbound GitHub calls on a cold metadata cache, where it previously blocked on up to six. Still deployable as a set - config/manifests/vc-due-diligence.yaml, PROMOTED from docs/demos/vc-due-diligence/system-manifest.yaml — not authored. The system name and short names are load-bearing: deployed names are f"{name}-{short}" and dd-lead/CLAUDE.md hardcodes its roster as `vc-due-diligence-dd-*`, so a tidier `vc-demo` + `founder` would deploy 11 healthy containers whose Deal Lead reaches nobody. Added the nine dd-lead -> specialist permissions (the manual post-deploy step the old copy told you to run by hand); dropped `prompt:` (overwrites trinity_prompt), `auto_start:`/`folders:` (not read by parse_manifest) and per-agent `resources:` (each dd-* template.yaml overwrites it at creation). dd-lead is listed FIRST so a creator hitting the default 10-agent quota loses a specialist, not the orchestrator. - The old copy gets a SUPERSEDED banner and the demo README points at the new location; keeping it (rather than moving) preserves any existing link, and the banner is what stops the two drifting. Tests - test_1931_catalog_intent.py (new, dependency-free): every bundled directory declares `hidden:`, it is a real bool, and the visible set is pinned to sage/scout/scribe. Own file so `import yaml` stays out of test_local_templates_listing.py's import block, and because _build_local_template's `bool(data.get("hidden", False))` destroys exactly the present-vs-absent information this asserts on. The RUNTIME default stays visible-by-default on purpose — flipping it turns a forgotten key into a silent absence, which is the worse failure. - test_1931_manifest_roster.py (new): validate_manifest over the glob, plus the assertion that would have caught the naming trap. It anchors on the SHORT NAME (`<prefix>-<short>` in a deployed template's CLAUDE.md must equal that manifest's resolved name), not on the manifest's own name — the latter goes vacuously green on precisely the rename it exists to catch. Verified to fire on both a system rename and a short-name rename, and to find zero false positives across all four bundled manifests. - test_local_templates_listing.py: `dd-` joins the visible-prefix ban; test_real_catalog_surfaces_starters_ahead_of_suite renamed and reworked — its `if dd_positions:` clause could now only go vacuous, so it asserts the priority: 20 mechanism instead, with the ordering clause generalised and labelled inert. - test_ent124_default_system_seed.py: the two on-disk checks widened from default-system.yaml to a glob over config/manifests/*.yaml, parametrised so a failure names the manifest. They are properties of any bundled manifest. Docs - config/agent-templates/README.md: the dd table moves out of "Starter templates" into its own "Demo fleet" subsection under "Not starting points", both demo manifests are named, and the authoring rule becomes the intent-declaration contract. - mcp-orchestration.md + mcp-server create_agent description (Invariant #13): drop the `github:abilityai/agent-ruby` example that will never again appear in list_templates. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…es (#1931) With DEFAULT_GITHUB_TEMPLATE_REPOS emptied, a default install has zero GitHub templates — and the section was wrapped in `v-if="githubTemplates.length > 0"`, so it silently VANISHED. requirements §4.5 promises "per-kind empty states teach the next action"; that promise was being honoured only by accident, because the count had never been zero before. Library.vue - New `noTemplatesAtAll` computed over the WHOLE /api/templates response (both sources). The section now renders on `!noTemplatesAtAll` — not `githubTemplates.length > 0 || !noTemplatesAtAll`, whose first disjunct is provably dead since githubTemplates is a filter over templates. The page-level "No templates configured" block is UNCHANGED and keeps sole ownership of the wholly-empty case; the 4-row truth table is inlined at the computed, and exactly one empty state renders in every row. - Placeholder card, marketplace-first (operator decision): the abilityai/abilities marketplace + create-agent wizards lead, because they exist today and a fresh install's Settings panel does not. Then the secondary "already have a repository?" action, then the curation hint. - The CTA is `useTemplate({ id: 'github-custom' })`, CreateAgentModal's own sentinel for the free-form owner/repo option — deliberately NOT `useTemplate(null)`, which is byte-identically the Blank Agent button two sections up and would land the user on the wrong option under a different label. The sentinel arrives via the existing `initial-template` prop and is explicitly exempted from that component's unknown-template reset, so no CreateAgentModal change is needed. - Only the curation hint branches on role (`useRole()`), mirroring LibrarySkillsSection.vue on this same page — the templates half must not ship the opposite convention to the skills half. The ACTION is offered to both roles so a non-admin is never left holding only an admin-only path. - Tag-along: the page-level hint said "Configure GitHub templates in config.py", which is not an operator surface and is now empty by design. Settings.vue — the destination must not dead-end The Library's own hint sends an admin to Settings → GitHub Templates, where a fresh install said "…or reset to defaults" next to a Reset button that is :disabled in exactly that state and would now reset to the same empty list. This change would otherwise satisfy the AC on the Library and newly violate it one click away. Two strings: drop the impossible action from the empty row, and stop badging an empty set as "Using defaults". Verified: `npm run build` clean. No e2e spec asserts any changed string — smoke.spec.js matches the headings 'Library' / 'Agent Templates' with exact: true (the new card's heading is "No GitHub templates configured"), and settings-tabs.spec.js only route-mocks /api/settings/github-templates. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…change (#1931) /update-tests + /sync-feature-flows tail pass. The riskiest claim in this change was verified only by READING: that emptying DEFAULT_GITHUB_TEMPLATE_REPOS cannot break an existing agent created from `github:abilityai/agent-ruby`, because get_github_template's `if repo in DEFAULT_...` branch and its "Dynamic" fallback are byte-identical two-line bodies. That is the sibling-path rule — a guard proven on one codepath has to be proven on every path reaching the same behaviour — so it is now proven by RUNNING: test_1931_empty_github_defaults.py - an unconfigured github: id still resolves with the list empty - the emptied and configured paths return the IDENTICAL template dict - get_all_templates() with [] makes ZERO outbound metadata fetches (the intended side-effect: no ThreadPoolExecutor, no HTTP, no PAT read) - counter-test: a CONFIGURED repo is still fetched, so the assertion above cannot go vacuously green if fetching breaks entirely - the shipped constant is [] Verified to fail when the list is refilled. `tests/lint_sys_modules.py` green (monkeypatch.setitem, no bare sys.modules assignment); order-independent (_metadata_cache cleared per load, since it is module-global and survives). Flow docs — two surfaces the plan had not named: - platform-settings.md (TMPL-001): the section said admins configure repos "replacing the hardcoded config.py list" and that no-DB-config falls back to "[...from config.py...]". Both now misleading. Records the empty default, that None and [] produce the same catalog and differ only in the badge, that Reset-to-Defaults reverts to empty (and is already :disabled there), that create capability is untouched, and the zero-outbound-calls side-effect. - system-manifest.md: a new bundled manifest is DATA, NOT A TRIGGER (BUNDLED_MANIFEST_PATH is hard-coded to default-system.yaml; nothing globs the directory) — the basis on which an 11-agent / ~40 GB manifest was safe to add. Plus the ent124 glob widening and the new roster guard. - feature-flows.md: one Recent Updates row. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
) Review findings on this branch's own new tests. 1. The roster guard walked `CLAUDE.md` only. A literal collaborator name is just as load-bearing — and breaks just as silently — in a slash command, and the sibling ent#239 check already treats `.claude/commands/` as a first-class shipped surface. Restricting the walk left four real literals unguarded in the bundled corpus: sage/.claude/commands/request-research.md -> acme-scout demo-analyst/.claude/commands/briefing.md -> research-network-researcher demo-analyst/.claude/commands/request-research.md -> research-network-researcher Widened to CLAUDE.md + .claude/commands/*.md + .claude/skills/**/*.md via a deduped, sorted `_prompt_files()` helper. Token pattern unchanged. Corpus: 13 -> 28 matching tokens across 4 manifests, zero offenders. Mutation-proved twice: renaming the manifest `name:` goes red (as before), and breaking a name inside a .claude/commands file now goes red too — the coverage that did not exist before. 2. `test_shipped_default_is_empty` did a bare `sys.path.insert(0, ...)` in the test body: a permanent, un-undone global side-effect (one duplicate entry per session) that `tests/unit/conftest.py` already makes unnecessary. Dropped; the test still passes standalone. 3. Dropped an unused `import yaml` inside the roster test, and corrected a comment claiming `_metadata_cache` "survives across loads" — each `exec_module` builds a fresh module, so the `.clear()` is defensive only. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The `test_manifest_resolved_names_satisfy_hardcoded_rosters` docstring said
restricting the walk to `CLAUDE.md` left "four" real literals unguarded. It is
three. Verified twice:
grep -rlE "acme-scout|research-network-researcher" config/agent-templates/
returns 6 files, of which exactly 3 are not `CLAUDE.md` —
`demo-analyst/.claude/commands/{briefing,request-research}.md` and
`sage/.claude/commands/request-research.md` — and an occurrence count confirms
one match per file. The parenthetical that follows already enumerated three;
only the count word was wrong.
Docstring-only. No assertion, scan surface, or behaviour changes.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…1931) gitleaks' default `curl-auth-header` rule flags the `-H "Authorization: Bearer YOUR_TOKEN"` line in the DEPLOY header comment of config/manifests/vc-due-diligence.yaml (entropy 3.121928). It is a documentation placeholder, not a credential, and is verbatim-identical to the pre-existing line in config/manifests/research-network.yaml:10 — that one never tripped the scanner only because the workflow scans the PR commit range, not the whole tree. So this PR followed the house convention rather than introducing a new practice; the manifest comment is left untouched. Add YOUR_TOKEN to the existing `regexes` allowlist beside the other CLAUDE.md-sanctioned placeholders (`your-api-key`, `your-domain.com`). Deliberately NOT a `paths` entry: per the note already in this file, a path allowlist is a PRE-SCAN file skip and would stop config/manifests/ being scanned for real secrets, whereas a targeted regex suppresses only this placeholder. Verified locally with the CI-pinned gitleaks 8.30.1 over the same commit range: 1 leak before, "no leaks found" after; a planted ghp_ PAT under config/manifests/ is still detected. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
08a9d93 to
2d48d10
Compare
Fixes #1931
A fresh install's Library advertised 14 local templates — 11 of them the
dd-*VCdue-diligence demo fleet — plus 6 GitHub repos last pushed Dec-2025/Jan-2026 that no
install had ever overridden. Both were presented as real starting points. They are not: the
dd-*agents only work as a deployed set, and the GitHub list was a bundled default nobodycurated. The catalog now shows 3 starters (
sage,scout,scribe) and 0 GitHubrepos.
What changed
hidden: trueon the 11dd-*templates via the existing bug: agent template catalog surfaces internal test/canary fixtures + a broken stub as real templates #1513 mechanism — omittedfrom
GET /api/templates, still creatable by id. The fleet stays deployable as a setthrough a bundled manifest.
DEFAULT_GITHUB_TEMPLATE_REPOS = []. The constant is kept, not deleted — TMPL-001'sNone-vs-[]fallback,routers/settings.py, and the Settings "defaults" badge allreference it, and trinity-enterprise#14 will repoint the same seam.
hidden:(CI-enforced). The runtimedefault is deliberately unchanged — flipping it would turn a forgotten key into a silent
absence.
.gitleaks.toml:YOUR_TOKENallowlisted (aregexesentry, notpaths). The newmanifest's DEPLOY comment reuses the sanctioned
Authorization: Bearer YOUR_TOKENplaceholderalready in
research-network.yaml:10, which trips gitleaks' defaultcurl-auth-headerrule;a
regexesentry suppresses only that placeholder, soconfig/manifests/stays scanned forreal secrets (a
pathsblock is a pre-scan file skip and would not).Deliberate decisions (not scope drift)
plan. The
abilityai/abilitiesmarketplace and itscreate-agentwizards are presented asthe recommended path; Settings → GitHub Templates +
owner/repois secondary. Theplan had these the other way round.
Settings.vueis AC-fix: add missing logging_config.py to backend Dockerfile #4 completion, not scope drift. The Library's new hint pointed at adestination that itself dead-ended — Settings said "No templates configured. Add a GitHub
repo above or reset to defaults" while the Reset button is
:disabledin exactly thatstate and the shipped default list is now empty. Fixing the origin without the destination
would have left the dead end one click further in.
docs/demos/vc-due-diligence/system-manifest.yaml, notinvented, and is named
vc-due-diligence.yamlon purpose. Deployed agent names arebuilt as
f"{system_name}-{short_name}"(system_service.py:382) anddd-lead/CLAUDE.mdhardcodes its roster as ninevc-due-diligence-dd-*literals. Anyother manifest name therefore ships 11 healthy containers whose orchestrator 404s on every
delegation — with green CI. A new guard
(
tests/unit/test_1931_manifest_roster.py) catches exactly that. The promoted copy also addsthe
dd-lead → specialistpermissions the demo left to a manual step and drops three keysthat were dead or harmful there.
Library.vuepage-level hintcopy; the ent124 test widening from a fixed path to a glob; the
test_real_catalog_surfaces_the_three_startersrename and its now-inert ordering clause; anda third test file (
test_1931_empty_github_defaults.py) that converts a read-only"these two branches are byte-identical" argument into a running proof.
Two intended side-effects
GET /api/templatesnow makes zero outbound GitHub calls on a cold metadata cache.BUNDLED_MANIFEST_PATHhard-codesconfig/manifests/default-system.yaml(system_seed_service.py:83), so nothing auto-deploysit.
Measured outcome
sage,scout,scribe)hidden:25 bundled template directories total: 3 visible, 22 hidden.
Verification
tests/unit(verify stage): 6012 passed / 18 skippedtests/unit(ship stage re-run): 6010 passed / 18 skipped / 2 failed — both failures areenvironmental, not branch-caused; see "Ship-stage re-run caveats" below.
#1931set + the 2 modified test files, re-run at ship stage after the docstring fix:69 passed (
test_1931_catalog_intent.py,test_1931_empty_github_defaults.py,test_1931_manifest_roster.py,test_local_templates_listing.py,test_ent124_default_system_seed.py)npm run build: clean/verify-local --skip-agent: PASS; integration 70 passed / 13 skipped / 2 deselected/app/config/manifests/vc-due-diligence.yamlis present in the builtbackend image, 6493 B byte-match, parses to
name = 'vc-due-diligence', 11 agents, zerovc-demo.Guard mutations all fail RED
dd-*hidden:keyname:→vc-demo.claude/commands/Ship-stage re-run caveats (host environment, disclosed)
The ship-stage full-suite re-run was done on a host whose environment differs from the verify
host. Two artifacts, neither branch-caused:
4 files could not be collected —
test_1771{a,b,c}_*_properties.pyneedhypothesis,which is a declared test dep (
tests/requirements-test.txt:26—hypothesis==6.161.5)simply not installed on this host. Excluded from the re-run; all four are untouched by
this branch.
2 failed —
test_1081_physical_meter.py::TestPerAgentMeter::test_available_floors_at_zero_over_ceiling[sqlite]and
::TestDisjointBulkMeter::test_max_respects_506_clamp[sqlite]. Shared-stateinterference from a second, unrelated
pytestprocess running concurrently on the same host(these tests exercise the fleet-wide
max_parallel_tasks_ceilingsetting, which feat(capacity): admin-configurable system-wide ceiling + agent-settings UI for max_parallel_tasks #506deliberately reads uncached from shared
system_settings). Evidence they are notbranch-caused:
tests/unit/test_1081_physical_meter.pyis byte-identical toorigin/dev(blob
622c4eb4);CI runs the suite without a competing process, so this should not reproduce there.
Pre-existing failure — disclosed, not branch-caused
tests/unit/test_1069_voip_call_path_param.py::test_flat_path_params_are_agent_name_not_nameimports
get_flat_dependant(line 214), which fastapi 0.141.1 removed.tests/requirements-test.txt:33floatsfastapi>=0.115.0with no upper bound, so whetherthis test passes depends on which fastapi a host resolves.
This branch leaves
tests/unit/test_1069_voip_call_path_param.py,src/backend/routers/voip.py,and
tests/requirements-test.txtbyte-identical toorigin/dev— verified by blob hash — soit cannot be branch-caused either way.
Follow-ups (listed, deliberately not filed)
docs/demos/vc-due-diligence/system-manifest.yaml. It still carriesprompt:(line 46), and
system_service.py:1143writes that fleet-wide viadb.set_setting("trinity_prompt", …). This PR only adds aSUPERSEDEDheader naming thehazard.
fastapiintests/requirements-test.txt— the unbounded>=above is why a green branch can go red on a different host.
template-processing.md:560-578documents aGITHUB_TEMPLATES = [...]literal at"
config.py:91-164" that does not exist (confirmed: the symbol is absent from a 380-lineconfig.py). Pre-existing rot, left alone because it is a live Path traversal in template resolution:local:<id>read escape, plusname:-derived credential staging that leaks another tenant's .mcp.json #1900 collision file.if repo in DEFAULT_GITHUB_TEMPLATE_REPOS:branch intemplate_service.py:602(also Path traversal in template resolution:local:<id>read escape, plusname:-derived credential staging that leaks another tenant's .mcp.json #1900's file this run).MULTI_AGENT_SYSTEM_GUIDE.mdCorbin/Ruby staleness.research-network.yaml/acme-consulting.yamlheaders document deploy commands that cannotwork.
dd-leadshould discover its roster vialist_agentsinstead of hardcoding nine names —the root fix for this whole class.
backend fails LOUD with
FORK_TO_OWN_REQUIREDplus remediation.Merge order
Four files collide with sibling PRs. No rebase is needed today —
origin/devis unmoved atthe base commit. First-merged wins; the others rebase.
docs/memory/requirements/core-agent.md§4.1…since #843.anchordocs/memory/feature-flows.mddocs/memory/feature-flows/template-processing.mdtests/unit/test_local_templates_listing.py🤖 Generated with Claude Code