Variable contracts: declare the values that cross an activity boundary - #503
Merged
Merged
Conversation
Fifty-five values were produced by one activity and consulted by another with no contract at either end. Each is now declared: the write on every activity that produces it, carrying the description the producing technique already gives it, and the read on every activity the guard finds consulting it. Where a path reaches a read before its producer runs — a loop-back, or a consumer earlier in the order — the write carries a default, so the value the reader finds is the empty one rather than nothing at all. remediate-vuln opens on its own start rather than work-package's, so two review-mode values the borrowed submit-for-review reads have no producer in that workflow. It owns them as the empty constants they are there. A declaration keeps the words of the technique's own description and drops its links: those resolve from techniques/ and the declaration lives in activities/.
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.
Summary
Fifty-five values were produced by one activity and consulted by another with no contract at either
end. Each is now declared: the write on the activity that produces it, the read on the activity that
consults it.
They were invisible until now because the guard holding the corpus to its contracts narrowed both
its derived reads and its derived writes to the workflow's declared namespace — and that namespace is
assembled from the declarations being checked, so a name nobody declared dropped out of both sides at
once. The paired server change in #502 fixes that and reports this shape as
undeclared-crossing.Stacked on #500 so the two can be reviewed apart and land together. Base is
workflow/496-activity-exits.How it surfaced
A smoke run of
work-packagewith a real worker failed its session-contract assertion: the run wroteprior_feedback_triageandrating_capwhile exitingstart-work-package, which declared neither.start-work-packagebindsreview-existing-feedback, whose outputs those are;submit-for-reviewbinds
review-summary, whose prose reads both. Nothing declared either, so nothing static could seeit and only the run could.
What is declared
79 findings, 55 values, 7 workflows —
work-package19,remediate-vuln17,substrate-node-security-audit17,workflow-design11,midnight-system-review7,workflow-authoring7,prism-evaluate1.Each write carries the description the producing technique already gives that output, so the
declaration and the operation say the same thing about the value.
Where a read is reached before its producer runs, the write carries a default. 54 of the
declarations sit on activities that consult a value earlier in the run order than the activity
producing it, or on a loop-back —
requirementsat 29 sites,changed_filesat 10,review_summaryat 5. The default means such a reader finds the empty value rather than nothing.remediate-vuln owns two values outright. It opens on its own
startrather thanwork-package'sstart-work-package, so the review-mode values that opener produces have noproducer in it. Declaring the write upstream left this workflow with a reader and no writer, which
is the borrowed-activity seam #491 named. It now declares both as the empty constants they are in a
workflow that remediates a vulnerability and never reviews a pull request.
Descriptions keep their words and drop their links. 13 descriptions taken from technique files
carried relative markdown links that resolve from
techniques/and not fromactivities/; one ofthem broke
check:resource-anchors.Verification
Verified against the paired server branch: all 30 guards pass with the new family at hard zero, the
1,097-test suite passes, and the walk snapshots are unchanged apart from the corpus SHA stamp —
declaring a contract moves no path.
The original defect is confirmed fixed on the original evidence:
check-session-contractover thesaved session from the failed smoke run reports
23 write(s) measured … OK.Non-goals
This declares the crossings that exist rather than redesigning the flows that make them. Where a
value arguably should not cross an activity boundary at all, that is a separate question.
substrate-node-security-auditproduces and consults bothdispatch_resultsanddispatched_results, so both are declared. That two names this close coexist is worth its own look.🤖 Generated with Claude Code