Skip to content

Activity body: the definition collapses in parts, and its identity always arrives - #442

Merged
m2ux merged 7 commits into
feat/delivery-cost-send-oncefrom
feat/delivery-cost-activity-body
Aug 7, 2026
Merged

Activity body: the definition collapses in parts, and its identity always arrives#442
m2ux merged 7 commits into
feat/delivery-cost-send-oncefrom
feat/delivery-cost-activity-body

Conversation

@m2ux

@m2ux m2ux commented Aug 6, 2026

Copy link
Copy Markdown
Owner

Summary

When a resumed worker asks for its activity again, almost everything in the response can arrive as a
short marker instead of the bytes: each bundled technique, the inherited rules block, each shared
block of a composed technique, each eagerly bundled resource. One part could not. The activity
definition was concatenated onto the response outside the delivery ledger, so no lookup happened and
no marker was possible — it was appended in full every time, to a worker still holding the previous
copy. Measured over eight activities of the main workflow, that was 70,957 of 184,684 characters,
38.4% of what a resume received.

Work item W10 of the delivery-cost epic #404. Stacked on #441, which this branch includes.

The identity is what makes the fix a split rather than a marker

A worker is required to confirm that the activity id the server returned matches the one it was
dispatched for, and to stop without executing a step if they disagree. That check reads the
definition. So the definition cannot collapse to a single marker the way a technique does.

It is keyed in parts instead. The identity — every scalar field of the definition — is always
delivered whole. The step list, the transitions, the outcome, and the artifact contract the server
synthesises from the steps' declared outputs are keyed separately, by content, under
activity:<field>:<hash>. That is the treatment a composed technique already gets, where the
invariant note and the item list are keyed apart so a shared preamble collapses even when the rest
differs.

Content-keying means no invalidation: an edited step list hashes differently, so it gets a different
key and delivers in full.

A field the splitter does not recognise stays with the identity, so a definition field the server has
never seen is delivered rather than silently dropped.

What it measures

The reference walk over thirteen gates of the main workflow, one identity per activity:

Before After
Re-request collapse 69.9% 83.5%
Characters re-requested 271,411 141,951

The epic body quotes 65.4% as the figure to beat. That reading predates the batched-dispatch merge,
which added the activity-worker role technique to every activity delivery; the same test on the
branch point reports 69.9%, and that is what the table above is read against.

Acceptance, item by item

  • A resumed worker's re-request returns the identity in full and the remainder as markers where the
    bytes are unchanged.
    Asserted on the real corpus: id: present, steps: a marker, response
    shorter.
  • The dispatched-activity confirmation still has an id to check on every delivery path, including a
    fully collapsed one.
    Asserted by parsing a definition whose every keyed section collapsed and
    reading id and version off it.
  • A forced full delivery is unaffected. Asserted with bundle: 'full' after a first delivery.
  • The reference walk records a higher collapse figure, with the body share falling. 83.5% against
    69.9%, above.

Scope of change

  • src/utils/activity-body.ts (new) — the split and the per-field projection.
  • src/tools/workflow-tools.ts — the delivery path reads the projection; the cost line reports how
    many definition fields collapsed and what they were worth.
  • src/utils/delivery.ts — the new namespace joins the ledger's key inventory.
  • tests/activity-body-delivery.test.ts (new, 9 tests) — the split loses nothing, an unrecognised
    field survives, a changed section delivers in full while its siblings collapse, and the two
    corpus-level assertions above.

No schema change, no definition change.

Non-goals

  • The eager bundle's budget behaviour. A marker costs nothing against the budget, so freed headroom is
    spent sending resource bodies the first delivery could not afford — that is the budget working, not
    re-delivery, and it is why a large resume figure can sit beside a small body share.
  • Re-warming a resumed worker's context, which is a consequence of gates waiting on a person.
  • Confirming on production runs that re-delivered characters have fallen. That is W11, and it waits
    on around ten completed gate-crossing sessions; the walk test is a regression guard, not evidence
    about production.

Investigation detail

engineering/artifacts/planning/2026-08-02-delivery-cost-epic/issue-417-activity-body-delivery.md
— the per-activity body-share table, from 17% on an activity that binds many techniques to 95% on one
that binds few.

m2ux added 2 commits August 6, 2026 12:38
Everything else a resumed delivery carries can arrive as a marker. The
definition is now keyed the same way, in parts: the identity and every scalar
field are always delivered whole, and the step list, transitions, outcome and
synthesised artifact contract are keyed by content under activity:<field>:<hash>.

The identity is what makes the split necessary. A worker confirms the returned
activity id against the one it was dispatched for and stops without executing a
step if they disagree, so that field survives however much else collapses — the
treatment a composed technique's invariant note already gets.

The reference walk over thirteen gates of the main workflow now collapses 83.5%
of a re-request, up from 69.9%, with the re-requested total falling from 271,411
to 141,951 characters. A forced full delivery still carries the whole definition.
The ledger's key inventory is the one place a reader learns what a delivery can
collapse, so the activity definition's per-field keys belong in it, with the note
that its identity fields are never keyed.
m2ux added 2 commits August 6, 2026 13:28
The resolution model asserted the activity body is always delivered, and its
namespace list did not carry the definition's own channel. Both now describe what
a delivery of the definition does: identity fields never keyed, the step list,
transitions, outcome and artifact contract each on their own hash.

The api-reference row for get_activity names what the response opens with, so a
reader learns the batch standing is in the text as well as in _meta.
m2ux added 3 commits August 6, 2026 18:08
Seven activities across five workflows carry a decisions: block between steps and
transitions. Holding the unkeyed text as one leading blob moved it ahead of the
step list in the delivery, so the definition a worker read was not in the order
it was authored in — valid YAML, and silent.

The split now holds runs in document order and the projection emits them in that
order, which makes the round-trip exact by construction. A test walks every
activity of the corpus and asserts it; that is the check that would have caught
this, so it is in the suite rather than in the description of the fix.
@m2ux
m2ux merged commit d6f0cce into feat/delivery-cost-send-once Aug 7, 2026
2 of 3 checks passed
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