Repository navigation
Co-core bump rule: resolve_dispatch_essence is notice, not coordination #57
Copy link
Copy link
Closed
Description
Problem
The co-core bump rule names resolve_dispatch_essence as part of the contract. A change to the contract needs coordination with Watcher first, not just notice. But Processor never calls resolve_dispatch_essence: grep -rn resolve_dispatch_essence src/ returns nothing on 540975e. Watcher resolves the essence on its own co-core pin and puts it on the command. Processor dispatches whatever essence arrives and never re-resolves it (spec §3, cannobserv#486 D1).
So a change to resolve_dispatch_essence can't change Processor's behaviour on its own, and the rule asks for coordination it doesn't need. It has happened twice:
- Take co-core's XML and feed extractors in step with Watcher, and re-run parity with a feed fixture #29 (0.32.0):
.xml/.rss/.atom→ the XML essences. Coordinated on Take cannobserv v0.32.0 in step with Processor: resolve_dispatch_essence maps .xml/.rss/.atom to the XML essences watcher#366, and Watcher's acknowledgement gated the deploy. The spec's own §5 reasoning says either order was safe. - JSON: take co-core's JsonExtractor (cannobserv#354) and add a jsonpath parity fixture #37 (0.38.0):
.json→application/json. Treated as notice, with the either-order reasoning in the bump note (JSON: take co-core's JsonExtractor (cannobserv#354) and add a jsonpath parity fixture #37 (comment)). That contradicts the rule as written.
The argument both times:
- An old Watcher keeps sending the ambiguous essence, which reaches the same extractor as before.
- A new Watcher's resolved essence reaches the old extractor on an old Processor, and the new one on a new Processor.
- The moved-digest list in the notice already covers what Watcher sees when the dispatch map changes for an essence Watcher sends today.
Where the rule is stated
AGENTS.md:21: "coordinated with Watcher only if it changes the contract: … orresolve_dispatch_essence"docs/DEPLOYMENT.md:461, "Bumping co-core" step 4- the spec: D5 (
:134) and §5 (:507-509)
Proposal
- Drop
resolve_dispatch_essencefrom the contract list in all four places. The contract becomes thecontent.process/content.derivedmodels andcanonical_textsemantics. - Say why, once, in §5. Essence resolution is the issuer's, on its own pin, and Processor never re-resolves. So a change to it is notice, carrying the either-order reasoning and the moved digests. It is never coordination.
- Guard the premise with a test, so the rule can't silently go stale. Assert that nothing under
src/processor/imports or namesresolve_dispatch_essence/extension_media_type, the same waygen_parity_goldens.py's import test works. If Processor ever starts resolving essences itself, the test fails, and the rule has to come back with it. - Amend the spec (an amendment entry), noting that Take co-core's XML and feed extractors in step with Watcher, and re-run parity with a feed fixture #29's coordination was more than the rule needed. The history stays as written.
Out of scope
- Watcher's own pin and its handling of the tiebreak.
- Changes to
EXTRACTOR_BY_ESSENCE. Those already reach Watcher as moved digests in the notice, which stays required on every bump.
Found while shipping #37.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Activity
gregoryfoster commentedon Oct 21, 2026
Hand-off from the burn-down epic #24, 2026-10-21. This is next, and it is the last open item before the epic returns to a parking lot (#54). Size S: docs and one test, so no deploy. The pre-flight is against
origin/main(a1a9e91, #58's head).The premise holds.
grep -rn 'resolve_dispatch_essence\|extension_media_type' src/ tests/ scripts/returns nothing. Processor dispatches the essence Watcher puts on the command and never resolves one itself.Where the rule is stated (current line numbers; #58 shifted DEPLOYMENT.md by one):
AGENTS.md:21, the "coordinated with Watcher only if it changes the contract: …" sentence.docs/DEPLOYMENT.md:462, "Bumping co-core" step 4.docs/specs/2026-09-29-processor-service-design.md: D5 at:134, and §5 at:509(the end of the contract list).:61(Take co-core's XML and feed extractors in step with Watcher, and re-run parity with a feed fixture #29: "so it is coordinated with Watcher") and:86(JSON: take co-core's JsonExtractor (cannobserv#354) and add a jsonpath parity fixture #37), and §5's per-bump notes at:468-484, record what happened.The change (the issue's proposal, which the coordinator agrees with):
resolve_dispatch_essencefrom the contract list in the four places above. The contract becomes thecontent.process/content.derivedmodels andcanonical_textsemantics.tests/test_gen_parity_goldens.py:29-40, which walks the AST. Walk everysrc/processor/**/*.pyand fail on any import of, orName/Attributeuse of,resolve_dispatch_essenceorextension_media_type.Gate (operator): tell Watcher? D5 is a promise Processor made to Watcher: #47 posted the restated D5 on CannObserv/watcher#325, and Watcher agreed to the original there. This change narrows when Watcher is consulted, so the coordinator recommends a short notice after the merge. CannObserv/watcher#325 is closed now, so post it on CannObserv/watcher#368, where #37's notice went. It should say:
Draft it in the PR. It needs the operator's approval: the earlier approval covered #37's two posts only. If the operator declines, say so in the closing comment.
Traps:
EXTRACTOR_BY_ESSENCEstays where it is. A change to the dispatch map is still Processor's behaviour, and it reaches Watcher as moved digests in the notice, which stays required on every bump. Don't widen the change to it (the issue's out of scope).processor_versionmove stays.Done when:
resolve_dispatch_essence, and §5 says why once;from co_core.pure.extract import resolve_dispatch_essencein a scratch copy (show the red in the PR);mainpush runs. No deploy: nothing undersrc/,deploy/,scripts/deploy.sh,pyproject.tomloruv.lockchanges.Out of scope:
EXTRACTOR_BY_ESSENCE;Ship: issue → branch in a worktree → plan (short) → TDD (the guard test first) → PR (
Closes #57if the notice is declined or already posted, otherwiseRefs #57) → FF merge →git pull --ff-only→ the notice. The closing comment gives each box with its evidence, the known limits, and the follow-ups (or "none").Kickoff prompt:
gregoryfoster commentedon Oct 21, 2026
Shipped in #60, FF-merged to
mainas359e102. No deploy: the merge changes onlyAGENTS.md,docs/andtests/(and nothing undersrc/,deploy/,scripts/deploy.sh,pyproject.tomloruv.lock).Done when:
resolve_dispatch_essence, and §5 says why once:AGENTS.md:21: the contract list only.docs/DEPLOYMENT.md"Bumping co-core" step 4: the list, plus a one-line pointer to §5.tests/test_pin.py::test_processor_never_resolves_a_dispatch_essence, which walks the AST, plustest_the_guard_catches_code_not_text(7 cases). The PR shows the red: the guard fails on a scratch copy withfrom co_core.pure.extract import resolve_dispatch_essenceplanted inprocessors/extract.py, namingline 16: resolve_dispatch_essence.mainpush at359e102: run 39659160499, lint and test. Locally: 696 passed, 14 skipped. Every skip is environmental: no.envin the worktree, and/etc/processoris unreadable as exedev.The premise, checked on co-core 0.38.0: Processor calls
extractor_for_essenceandextraction_overrides_for_essence, and neither of them callsresolve_dispatch_essenceorextension_media_type.Known limits:
getattr(m, "resolve_dispatch_essence")), which would be deliberate evasion rather than drift.src/processor/only. That is everything that runs;scripts/isn't runtime.Follow-ups: none.
gregoryfoster commentedon Oct 21, 2026
Review round 1 shipped in #61, FF-merged to
mainas18deb3c. CI is green on the PR (run 39661447910) and on themainpush (run 39683627450). No deploy: onlydocs/andtests/changed.test_pin.pydocstring said the rule reverts if Processor "resolves essences itself". They now say what the guard actually checks: that Processor calls co-core's resolvers. Resolving an essence any other way is forbidden by Section 3, and a co-core bump can't change it.18deb3c.brainstormingoverride with a vendor symlink and anAGENTS.mdpreference.