fix: activate against core main — pluginUi nav, optional_requires (0.3.0) - #7
Merged
Merged
Conversation
…3.0) Verification pass against omadia core origin/main (9feb3ad3), the first core carrying the whole C9-C11 contract surface, with @omadia/plugin-api 1.5.0. Two real defects, both of which stopped the plugin working against that core. The nav entry hand-built a percent-encoded href. That is the one spelling core's HREF_SEGMENT refuses, and #798 deliberately kept the rule strict rather than widening it as the 2026-08-20 acceptance run's local patch assumed — so registerNav threw, the throw propagated out of activateInner, and the plugin did not activate at all. C9 closed this from the other side: declare `pluginUi: true` and the kernel renders the identical URL from the id it already holds. A recording double accepts any nav entry, which is why a green suite never saw it; the shape is now asserted directly. turnContext@1, githubAppJwt@1, usageTelemetry@1 and conductorRoles@1 move from `requires:` to `optional_requires:`. Core's capability resolver and install gate read `requires:` only, so listing a survivable capability there made this plugin uninstallable on stock core for four capabilities activate() is written to live without, each with a logged degradation. graphPool@1 stays the single hard requirement. Resolution moves to ctx.services.getOptional behind an optional-method guard, so a core predating plugin-api 1.4.0 still activates through the get() fallback; both paths are driven by tests. The nine C11 seedLedger witnesses needed no change: each is already a single SELECT returning one boolean row, built from to_regclass, information_schema.columns or a pg_constraint join, and they run clean under core's READ ONLY savepoint over the extended protocol. permissions.sql.ledger already satisfies the plg_<sanitized-id>_ rule. The activate() double was lenient on two points that mattered here, and is not any more: services.get/getOptional now throw for a capability declared in neither manifest list, and the declared set is parsed from manifest.yaml rather than restated, so a forgotten entry fails in this suite instead of against a real core. Acceptance: 38 PASS / 33 FAIL / 2 BLOCKED against plain origin/main, where all 33 failures share one cause — the two dev-platform publicPaths exemptions C12 (#807) deletes, not yet merged. Re-run against a core carrying C12: 71 PASS / 0 FAIL / 2 BLOCKED, same artifact, no plugin change. Suite is 1,316 tests, 0 fail, 0 skipped with the Postgres suites running. Records a new core gap (G7) in docs/ACCEPTANCE-RUN-2026-08-21.md: core runs ctx.sql.runMigrations() itself before activate(), so the C11 handoff can only ever report alreadySeeded and its skippedNoWitness alarm never fires.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Verification pass of this plugin against omadia core
origin/main(9feb3ad3) — the first core carrying the whole C9–C11 contract surface (optional_requires,ctx.services.getOptional,pluginUinav, core migrations at boot,ctx.sql.seedLedgerwith the read-only witness fence) at@omadia/plugin-api1.5.0.It found two real defects. Both stopped the plugin working against that core, and neither was a degradation — the first prevented activation outright.
The two fixes
1. The nav entry was unregisterable → the plugin did not activate
This plugin's id is scoped, so the only URL that resolves is the percent-encoded one (raw splits into two path segments and 404s). That is exactly the spelling core's
HREF_SEGMENTrefuses — and #798 deliberately kept that rule strict rather than widening it the way the 2026-08-20 acceptance run's local patch assumed, because the shell decides "core destinations win" by comparing hrefs for string equality and percent-encoding breaks the comparison.So the patch this repo was implicitly waiting on was never going to land. C9 closed it from the other side: the plugin declares
pluginUi: trueand the kernel renderspluginUiHref(id)itself. Byte-identical URL, no plugin ever hand-spells a percent-encoded href.registerNavthrew, the throw propagated out ofactivateInner, and activation failed. A recording double accepts any nav entry, which is why a green suite never noticed — so the shape is now asserted directly (pluginUi === true, nohref).2. Four survivable capabilities were declared as hard requirements
turnContext@1,githubAppJwt@1,usageTelemetry@1,conductorRoles@1move fromrequires:tooptional_requires:(C9 / core #795).Core's capability resolver and install gate read
requires:only, so listing a survivable capability there made this plugin uninstallable on stock core for four capabilitiesactivate()is explicitly written to live without — each with a logged, documented degradation.graphPool@1stays the single hard requirement.Resolution moves to
ctx.services.getOptionalbehind an optional-method guard, so a core predating plugin-api 1.4.0 still activates through theget()fallback. Both paths are driven by tests.Checked and found already correct
seedLedgerwitnesses. Each is already a singleSELECTreturning one boolean row, built fromto_regclass,information_schema.columnsor apg_constraintjoin — no casts that throw on a missing relation, no multi-statement strings, no writes. They run clean under core'sREAD ONLYsavepoint over the extended protocol.permissions.sql.ledgerisplg_omadia_dev_platform_migrations, inside theplg_<sanitized-id>_namespace.Test-double fidelity
The
activate()double was lenient on two points that mattered here:services.get/getOptionalnow throw for a capability declared in neither manifest list, matching the kernel since C2b.manifest.yamlrather than restated in the test, so a forgotten manifest entry fails in this suite instead of against a real core.test/manifest.test.tsasserts the exactrequires:/optional_requires:sets rather than membership — this regression arrives one promoted line at a time.Acceptance
scripts/acceptance-local.mjs, same artifact, two cores:origin/main@9feb3ad3origin/main+ C12 (feat/470-c13-residue@322afd19)All 33 failures on
mainhave one cause: the two dev-platformpublicPathsexemptions that C12 (byte5ai/omadia#807) deletes, not yet merged. Core activates the plugin fully and then tears it down over the collision, so every downstream row reads404 — route not mounted. With C12 present: 0 FAIL, no plugin change. Re-run againstmainonce #807 lands; no plugin change is expected.The two BLOCKED rows are unchanged from 2026-08-20 and honest: core exposes no tool-registry endpoint to probe chat-tool registration, and
acceptance.md§3.15 has not decided the uninstall lifecycle for grant rows.Full record:
docs/ACCEPTANCE-RUN-2026-08-21.md.Core gaps
Four of the six gaps from 2026-08-20 are closed on
main(G1 SQL gate, G2 optionality, G3 boot migrations, G5 nav href). G6 is C12, merged on its branch. Two remain:status: "active". This run is the proof:§3.9 activationreported PASS above a plugin core had already deactivated.toolPluginRuntime.ts:374-394callsctx.sql.runMigrations()beforeactivate()whenever the manifest declarespermissions.sql.migrations, butseedLedgeris documented to run insideactivate()beforerunMigrations()(plugin-api/src/pluginContext.ts:2071-2087). Measured against a database carrying core's donor rows and all nine tables — expected 9 seeded / 0 applied, observed core applying 9 first and the handoff reporting0 seeded, 9 already seeded. Not data loss (the files are idempotent), but theskippedNoWitnessalarm — the one output C11 exists to produce — can never fire. Needs a core issue; a plugin cannot fix it from its side.Verification
npm ci && npm run typecheck && npm run build && npm test && npm run package -w packages/plugin— all clean against coremain.plugin786 /runner-shim76 /daemon+ui454) with the Postgres suites actually running. Remaining skips are the two needing a builtdev-runnerimage.package.jsonandmanifest.yamltogether; the drift guard passes and the 0.3.0 ZIP is 525,131 bytes.Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.