Repository navigation
Conversation
Every worked example, template, and pattern entry in examples/library/catalog.yaml now records validation_status (validated or guidance), sdl_sections, intended_user, and limits. The gate rejects an entry whose status is outside the vocabulary, a template that is not validated, a pattern that claims validation, an unknown intended user, empty limits, or a section name that is not a current SDL section. Validated worked examples are now parsed through parse_sdl_file and fail on errors or advisories, and a validated entry must list only sections present in its SDL. The catalog description no longer calls every entry validated. The entry checks live in a new support module, tools/example_library_checks.py, because tools/check_example_library.py was already 488 lines against SonarCloud's 500-line file limit. The template-body SDL check moves there with its rule ids and messages. The module imports raes at module level, so the example-library-template-import rule for a failed raes import is removed. The top-level fields that are not sections come from tools/sdl_catalog_parity/_paths.py, which the SDL catalog parity gate keeps in step with specs/sdl/sections.md. examples/README.md documents the fields and what the gate checks.
…laim notes
Add two scenario templates beside minimal-validated-scenario:
segmented-network-scenario (two switched segments, linked hosts with
fixed addresses, HTTPS-only access rules, a service feature) and
parameterized-scenario (host operating system, size, instance count, and
service port from declared variables). Both bodies pass the SDL parser
and semantic validator with no advisories, and both are cataloged with
the entry metadata.
Every template now carries a validation list of commands with their
expected results. The gate requires the field, and
tools/example_library_checks.py checks that it is a non-empty list of
mappings with non-empty command and expected strings. The gate does not
run the commands.
examples/README.md lists what each scenario template shows and does not
claim, how to validate an adapted copy with raes semantic validate, and
that a ${name} placeholder in a template body must name a declared
variable.
… studies Add two templates whose bodies are experiment-authoring-input-v1 documents: seeded-run-plan (run count, seed, and episode controls for one task) and two-condition-study-design (a treatment factor, two compared conditions, and the runs per condition). Both pass the experiment authoring-input loader, parse_experiment_spec. A template's catalog entry may now declare contract: experiment-authoring-input-v1. Such an entry names experiment-author as its intended user and lists no sdl_sections, and the gate validates its body with the experiment loader instead of the SDL parser. Worked examples and patterns stay SDL. examples/README.md separates the SDL, experiment-input, guidance, and unsupported parts of the task, run, and study surfaces, including why there is no experiment-task-v1 template, and gives a command to validate an adapted experiment template.
doublewhy
force-pushed
the
379-participant-behavior-patterns
branch
from
October 9, 2026 15:05
60ba521 to
7c0a1a6
Compare
…ated example links Add three participant behavior patterns (scenario-local behavior specification, reusable module unit, tool affordance) and give the existing contract-binding pattern the same shape: required_fields, authoring steps, and validation commands that run. Two new validated templates, tool-affordance and reusable-behavior-unit, are the executable examples. The reusable-unit pattern checks an importing scenario with raes sdl resolve and raes sdl verify-imports, or with parse_sdl_file. Pattern catalog entries may now record example_refs. The example-library gate requires each one to name a worked example or template whose validation_status is validated, so a pattern links only to examples that the gate itself parses and validates. Each entry's limits state what it does not show, including the import limits recorded by the DSL-116 and DSL-117 verification.
doublewhy
force-pushed
the
379-participant-behavior-patterns
branch
from
October 9, 2026 16:34
7c0a1a6 to
7f4599e
Compare
doublewhy
marked this pull request as ready for review
October 9, 2026 17:02
9 of 11 tasks
This branch has not been deployed
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
Builds on #1458 (and through it #1445 and #1438); review those first. Until they merge, this PR also shows their commits,
6fa7bdab,f397d0a4and88975279. This PR's own change is commit7f4599ea.Issue #379 asks for a short catalog of participant behavior patterns tied to current SDL support. Each entry states its intended use, required fields, validation status and known limits, and links an executable example only when that example passes the normal validation path.
Requirement-level verification of the behavior surfaces is in two open PRs: #1426 (#297, DSL-116 behavior specifications, reusable and scenario-local) and #1440 (#298, DSL-117 tool affordances). On dev, DSL-116 is DRAFT and DSL-117 is ACTIVE. This PR does not depend on either PR, and no committed file references them. The catalog's claims are reproduced on this branch: the new tests cover the import composition and the four limits that describe behavior, and probes run on this branch cover the
required_fieldslists and therealization_profile_reflimit (Test Plan). Merge order does not matter: I merged #1440's head (600080a9), #1426's head (6fb57a4b), and then both, into this head without committing, and each time the new tests, that PR's own tests and the gate passed.Three of the limits restate gaps that #1426 and #1440 recorded. The fourth, that
raes semantic validaterejects a document that declares imports, is a designed limit:docs/explain/sdl/parser.mdsays in-memory parsing rejects imports by design. The reusable-unit pattern checks an importing scenario withraes sdl resolvefollowed byraes sdl verify-imports, or withparse_sdl_file.The participant behavior surface now has four patterns, three of them new:
participant-behavior-contract-binding(existing): binds agent actions and views to action contracts and observation boundaries. It gainsrequired_fieldsand validation commands that run.participant-behavior-specification(new): one scenario-local behavior specification over a participant's declarations.participant-behavior-reusable-unit(new): a behavior specification exported from a module unit and imported under a namespace.participant-behavior-tool-affordance(new): a tool content item bound to the action contracts and observation boundaries it serves.Two new templates are the executable examples.
tool-affordanceis the first library example that authors a tool affordance.reusable-behavior-unitis a module unit that the gate validates as a standalone scenario. The tool-affordance pattern names the tool by its bare content name. #1440 rewrites a bare name exactly as dev does, so the pattern composes the same way before and after #1440 merges.How this meets the issue's points:
intent,use_whenand a newrequired_fieldslist. Each list is checked in both directions (Test Plan). Removing or breaking a listed field in a copy of a template body fails validation, and a scenario that holds onlynameand the listed fields validates with no advisories.guidance, which feat(examples): add machine-checked metadata to example library entries #1438 requires for patterns. A new catalog field,example_refs, links its examples. The gate requires each ID to name a worked example or template whosevalidation_statusisvalidated, so a pattern links only to examples that the gate itself parses and validates.limitssay what it does not show. The reusable-unit entry states the three import limits: role refs are not scoped to one import,raes semantic validaterejects an importing scenario, and an invalid imported declaration raises a raw pydanticValidationError. The tool-affordance entry states that an importing scenario cannot add an affordance for an imported participant.Requirement UIDs
requirement_refsas context. No requirement record or traceability line changes.Related Issues
Closes #379
ADR Impact
Changes
examples/library/patterns/participant-behavior-specification.yaml,participant-behavior-reusable-unit.yamlandparticipant-behavior-tool-affordance.yaml(new): each hasintent,use_when,required_fields,authoring_stepsandvalidation. The tool-affordancerequired_fieldsalso name the fields of theview_rulesentry that classifies the affordance. The reusable-unitvalidationlists the gate, aparse_sdl_fileone-liner,raes sdl resolveandraes sdl verify-imports; the other two list the gate andraes semantic validate.examples/library/patterns/participant-behavior-contract-binding.yaml: addsrequired_fields, including that an observation boundary needs at least oneobservable_refsorevidence_refsentry. Its onevalidationentry,command: parse_sdl_file, was a function name rather than a command. It becomes the gate command and araes semantic validatecommand. One authoring step now names theobservation_boundariessection.examples/library/templates/participant_behavior/tool-affordance.yaml(new): a standalone scenario with a tool content item, ascanaction contract, an observation boundary that lists and classifies the affordance, and a behavior specification whose affordance binds the three.examples/library/templates/participant_behavior/reusable-behavior-unit.yaml(new): a module unit (example/scan-behavior1.0.0) that exports its participant, action contract, observation boundary and behavior specification. The behavior specification names its participant withparticipant_refs.examples/library/catalog.yaml: catalogs the two templates and three patterns, addsexample_refsto all four participant behavior patterns, and gives each new entry itssdl_sectionsandlimits. Other surfaces are unchanged.tools/example_library_checks.py: newcheck_example_refswith rule idexample-library-entry-examples. Only pattern entries may recordexample_refs. The value must be a non-empty list of IDs of validated worked examples or templates, on any surface. An entry whoseidis not a string is left to the existingexample-library-entry-idrule.tools/check_example_library.py: callscheck_example_refsonce per catalog and checks that a pattern's optionalrequired_fieldsis a list (480 lines,wc -l).examples/README.md: the library table lists the new files under a "Patterns" column. The metadata table gains anexample_refsrow. A new "Participant behavior patterns" subsection lists the four patterns, their validated templates and what they do not claim, and namesraes sdl resolvefollowed byraes sdl verify-importsas the command-line check for an importing scenario.implementations/python/tests/test_issue_379_participant_behavior_patterns.py(new), 24 cases in six functions:example-library-entry-examples: a guidance worked example, a pattern, an unknown ID, an empty list, a string, andexample_refson a template or on a worked example. A stringrequired_fieldsfails withexample-library-pattern-field-type. Four malformed catalogs report only their existing failure: a surface, apatternsfield and an entry that have the wrong type, and a validated template whoseidis a list (example-library-entry-id).raes semantic validate, the documented command, succeeds on the three participant behavior template bodies and rejects a scenario that imports the unit.raes sdl resolvethenraes sdl verify-importson that importing scenario:resolvewritesraes.lock.jsonand prints its path, andverify-importsprintsimports verified. With a bare-name ref (red-agentforalpha.red-agent),verify-importsexits 1 withSDLValidationError.alpha(1.0.0) andbravo(>=1,<2), compiles with each import's specification covering only its own participant. Withparticipant_role_refsinstead, each covers both imports' participants, as the limit states.alpha.red-agentfails becausealpha.red-viewdoes not classify it.lifecycle_statein the unit raisesSDLParseErrorwhen the unit is parsed alone and a pydanticValidationErrorwhen it is imported.raes semantic validaterejecting an importing scenario, the importing-scenario affordance and the rawValidationError. A change to any of these behaviors fails its case, so the catalog limit has to change with it.Test Plan
All commands ran from the worktree root on head
7f4599ea, under CPython 3.14.4 from the project environment, unless a paragraph names another head. The base isorigin/devat35122105plus the #1438, #1445 and #1458 commits.I ran each documented command:
uv run --project implementations/python --frozen python tools/check_example_library.pyexited 0 and printed nothing.tool-affordancebody, then theaction-contract-observation-boundarybody, asmy-scenario.sdl.yaml. Each time,uv run --project implementations/python --frozen raes semantic validate my-scenario.sdl.yamlprintedvalidate: successand exited 0.reusable-behavior-unitbody asscan-behavior.sdl.yaml, next to amy-scenario.sdl.yamlwith one import (namespacealpha, version1.0.0). The documentedparse_sdl_filecommand printed['alpha.red-scan-behavior']and exited 0.raes semantic validateprintedvalidate: successon the unit, and on the importing scenario it printedvalidate: invalidanderror [sdl.parse] SDL input was rejected at the parse stage., with exit 1.uv run --project implementations/python --frozen raes sdl resolve my-scenario.sdl.yamlprintedraes.lock.jsonand exited 0, andraes sdl verify-imports my-scenario.sdl.yamlthen printedimports verifiedand exited 0.raes.lock.json, after its run.The
required_fieldslists rest on two kinds of probe, each run by a scratch script (since deleted) in the same environment.Necessity: removing or breaking a listed field in an edited copy of a template body fails validation. These probes ran on the first head,
60ba5216, except the boundary and view-rule probes, which ran on this head. The template bodies are the same on both heads.projection_basis,redaction_policyandlatency_profilefailed with "participant observation boundary requires observable_refs or evidence_refs", both as thereusable-behavior-unitred-viewwithout itsevidence_refsand in a minimal scenario; adding oneevidence_refsor oneobservable_refsentry passed. Anobservation_effectwithouttarget_refsorevidence_refsfailed; ano_effectwithout them passed. An agent action that is not anaction_contractskey and an undeclared agent boundary each failed.action_contract_refsfailed with "widens its owning behavior specification". Removing the boundary's view rule or itsobservable_refsentry failed the classification check. An affordance action that the participant does not declare failed with "is outside participant". Atool_refthat names a node failed. A second, classified affordance with the same relation failed as a duplicate. Omittingtool_refpassed.information_ref,boundary_class,dispositionorvisibility_basisfailed with "Field required". Aninformation_refthat names another affordance failed with "must be explicitly classified by observation boundary 'red-view'". Anevidence_onlyrule failed withoutevidence_refsand passed with them. Adisclosedrule withoutdisclosure_rulefailed for each of the seven classes tried. Adiscovered,inferredordeceptiverule withoutdisclosure_rulefailed for each of the five classes the pattern names and passed forobservable_resourceandtool_output. Each of these passed with adisclosure_rule.realization_profile_refofno-such-manifestpassed and a blank one failed. An ungovernedbehavior_mode, an unknown feature, an unpublished evidence contract and an undeclared authority scope ref each failed.versionpassed, because it defaults to any version.version: '>=2'failed with "requested version '>=2' but module declares '1.0.0'". References to unexported declarations failed with "does not reference a declared agent" (andaction_contract), and so did a bare name. A unit without a module block failed with "Imported SDL units require an explicit module descriptor".Completeness, on this head: a scenario with only
nameand the fields that a list names validated withparse_sdland gave no advisories. That held for contract binding alone, for a behavior specification added to it, and for a tool affordance added to that, with its boundary entry andview_rulesentry. A unit with a module block (id,version, andexportsnaming the behavior specification) over the same declarations, imported by a scenario with onlynameand one import withsourceandnamespace, parsed withparse_sdl_fileand gave['alpha.spec']. On the previous head, the contract-binding list did not name the boundary'sobservable_refsorevidence_refsrequirement, and the tool-affordance list did not name the fields of theview_rulesentry it requires. This head lists both.uv run --project implementations/python --frozen --all-extras python -m pytestontest_issue_379_participant_behavior_patterns.py,test_issue_380_experiment_templates.py,test_issue_378_scenario_templates.py,test_issue_381_example_catalog_metadata.pyandtest_example_library_policy.pywith-q -p no:cacheproviderpassed: 63 passed (24 new). None of the modules has integration-marked cases, and-m integrationdeselects all 63.Regression checks:
tools/check_example_library.pyandtools/example_library_checks.pyfrom88975279and kept the new tests, templates and catalog. 8 of the 24 new cases failed: the sevenexample_refsviolations and the stringrequired_fields. The other 16 pass on both versions. They are the two allowed links, the four malformed-catalog cases, and the ten template, CLI and import cases, which do not depend on the checker. With the change restored, all 24 pass.idfilter removed fromcheck_example_refs, thetemplate-id-not-textcase failed withTypeError: cannot use 'list' as a set element (unhashable type: 'list'). With the filter, it passes.A coverage.py branch report over the same five modules covers every line and branch of
tools/example_library_checks.py(125 statements, 44 branches).Merge order with #1426 and #1440: in this worktree I ran
git merge --no-commit --no-ffwith #1440's head600080a9, then with #1426's head6fb57a4b, then with both, and rangit merge --abortafter each. Each merge applied without conflicts. With600080a9, the 24 new cases and the 27 intest_issue_298_tool_authoring.pypassed (51 passed) and the gate exited 0. With6fb57a4b, the 24 new cases and the 18 intest_issue_297_behavior_authoring.pypassed (42 passed) and the gate exited 0. With both, 69 passed and the gate exited 0.nox -s verify-fast-feedback -- --base-rev origin/dev,nox -s lintandmake policypassed, with every non-skipped stage green. The runner skippedpolicy / requirement governanceon its own, because the branch resolves no requirement UID and no requirement-scope file exists for #379.CI on head
7f4599ea: run 37960114996 (CI) passed, as did Docs (37960114513), Bootstrap qualification (37960114792) and CodeQL (37960108972). All 32 checks pass, withdeployskipped. The SonarCloud quality gate is OK on7f4599ea: 0 new issues, 99.5% coverage on new code and 0.0% duplication.Earlier heads: CI run 37946004145 on the first head,
60ba5216, passed every check exceptsonar. SonarCloud reported python:S3776, cognitive complexity 16 where 15 is allowed, in_catalog_entries;7c0a1a64moved the per-field loop into a new helper,_field_entries. CI run 37949167549 on7c0a1a64passed all 32 checks, withdeployskipped, and the SonarCloud gate was OK.Changes since
7c0a1a64, after a pre-push review: the tworequired_fieldsadditions above,action_contractsin the tool-affordance pattern's catalogsdl_sections, the string-idfilter incheck_example_refswith its test case,raes sdl resolveandraes sdl verify-importsin the reusable-unit pattern and the README with their test, and this description, which no longer says that the patterns rely on #1426 or #1440.Not run locally: the docs lanes, because no file under
docs/or a Vale entry point changed;examples/README.mdis outside the Sphinx source and the Vale file set. No package source,pyproject.tomloruv.lockchanged, and no pinned scenario is touched, so the research evidence captures need no republish. No test needs Docker.Ground Control Checks
make policyexited 0, and the only skipped stage was requirement governance.Pre-push code review: a review of
7c0a1a64returned findings, and this head addresses each one ("Changes since7c0a1a64" in the Test Plan). No separate test-quality review was run.Traceability
examples/library/patterns/participant-behavior-specification.yaml,examples/library/patterns/participant-behavior-reusable-unit.yaml,examples/library/patterns/participant-behavior-tool-affordance.yaml,examples/library/patterns/participant-behavior-contract-binding.yaml,examples/library/templates/participant_behavior/tool-affordance.yaml,examples/library/templates/participant_behavior/reusable-behavior-unit.yaml,examples/library/catalog.yaml,tools/example_library_checks.py,tools/check_example_library.py,examples/README.mdimplementations/python/tests/test_issue_379_participant_behavior_patterns.pyChecklist
feat(examples), because the new library entries are user-visible.examples/README.mddescribes the new entries.Documentation
Updated:
examples/README.md(library table, metadata table, new "Participant behavior patterns" subsection). Verified unchanged:docs/explain/getting-started.mdline 63 still describes the library accurately, and line 66 already namesraes sdl resolveandraes sdl verify-importsfor imports.