Skip to content

declare behaviour failure patterns once and generate their catalog (P196) - #1736

Merged
trissim merged 18 commits into
mainfrom
feat/p196-behaviour-catalog
Oct 19, 2026
Merged

trissim merged 18 commits into
mainfrom
feat/p196-behaviour-catalog

Conversation

@trissim

@trissim trissim commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Outcome

Each behaviour-failure pattern is one BehaviourPattern subclass. Its signature, existing check objects and source citations live on that class. DeclaredFamily / AutoRegisterMeta owns membership; class objects identify patterns, and document headings derive from their declarations. There is no pattern-name roster, identity switch or second registry. docs/agents/behaviour-catalog.md is generated; the equality check rejects any hand edit.

There are 14 pattern declarations: nine existing-check patterns and the five seeded declarations from 1e6e032b2. Adding a pattern is one class and regeneration.

What remained, and what changed

Ownership/source evidence

Before: catalog imports commander.order; references wrapper functions; import-time commander configuration changes spill across 16 commander/test files. Postmortem coverage materializes a dictionary of lists of pattern-name strings.

After: BehaviourPattern owns section() and catalog(), each leaf owns its facts, the existing declared-family mechanism supplies membership, and coverage walks class references directly. Only tests/test_behaviour_catalog.py imports the catalog module; the module's __main__ is the generation entrypoint.

Used the existing refactor-audit Package/ParsedModule tooling under Python 3.14 for the source census: 383 production modules, 477 test modules, 34 tool modules; no parse omissions. Inspected declarations, imports, field writes, decisions and consumers; all 14 pattern classes declare their own signature/checks/sources. Also parsed all nine installed metaclass_registry modules and read AutoRegisterMeta.__new__ plus Core's _FamilyMeta/DeclaredFamily registration path. Dynamic import binding is not established by this syntax query; this catalog uses direct imports and class references. The initial NRA import lacked tree_sitter in Core's environment, and NRA's own Python 3.12 could not parse Core's syntax; those attempts are not presented as completed scans. The Python 3.14 refactor-audit census had zero omissions. Applicable catalog precedents: MEMB-1, MEMB-4 and AGENT-2.

Reproduce owner/consumer search:

rg -n 'BehaviourPattern|SeedCatalog\(' src tests tools --glob '*.py'

Requested new-case proof

Added only this temporary sixth seeded declaration (there were already nine non-seeded patterns):

class SixthSeedPattern(BehaviourPattern):
    signature = "Throwaway sixth seed: one new declaration appears without editing a roster."
    checks = (CallableCheck(PlainText),)
    sources = (SeedCatalog(999),)

Ran the actual generation entrypoint:

PYTHONPATH=src /home/ts/code/projects/agent-comms/.venv/bin/python -X faulthandler \
  -m agent_comms.behaviour_patterns > docs/agents/behaviour-catalog.md

Exact catalog diff (no registry, consumer or other declaration edit):

@@ -162,3 +162,13 @@ Checked by:
 - not enforced here: P201 (#1739)
 
 Learned from: seed catalog pattern 18 (claude-ai message 1c8729ba0ed7)
+
+## sixth_seed
+
+Throwaway sixth seed: one new declaration appears without editing a roster.
+
+Checked by:
+
+- check in `agent_comms.todos.PlainText`
+
+Learned from: seed catalog pattern 999 (claude-ai message 1c8729ba0ed7)

The seeded-class count became 6. Removed the throwaway class, regenerated and verified both source and generated document exactly matched the pre-experiment versions.

Requested drift proof

Changed only the generated document's first line by hand. Ran:

PYTHONPATH=src timeout 300 /home/ts/code/projects/agent-comms/.venv/bin/python \
  -X faulthandler -m pytest -o addopts='' \
  --basetemp=/home/ts/.cache/agent-scratch/pi-catalog/drift-test \
  tests/test_behaviour_catalog.py::test_behaviour_catalog_members_name_existing_checks_and_generate_the_file -q

Actual failure, exit 1:

> assert (ROOT / "docs/agents/behaviour-catalog.md").read_text() == BehaviourPattern.catalog()
E AssertionError: assert '# Hand-edite...8729ba0ed7)\n' == '# Behaviour ...8729ba0ed7)\n'
E - # Behaviour catalog
E + # Hand-edited catalog (deliberate drift proof)
tests/test_behaviour_catalog.py:21: AssertionError
FAILED tests/test_behaviour_catalog.py::test_behaviour_catalog_members_name_existing_checks_and_generate_the_file
1 failed, 1 warning in 9.42s

Regenerated afterward; no deliberate drift remains.

Final verification

PYTHONPATH=src timeout 300 /home/ts/code/projects/agent-comms/.venv/bin/python \
  -X faulthandler -m pytest -o addopts='' \
  --basetemp=/home/ts/.cache/agent-scratch/pi-catalog/merged-confirm \
  tests/test_behaviour_catalog.py tests/test_declared_family.py -q
# 9 passed, 1 warning in 14.25s

/home/ts/code/projects/agent-comms/.venv/bin/python -m ruff check \
  src/agent_comms/behaviour_patterns.py tests/test_behaviour_catalog.py
# All checks passed!

git diff --check
# clean

The warning is the environment's missing pytest-timeout plugin (Unknown config option: timeout); the requested outer timeout 300 and Python faulthandler were used. No suite-delta claim is used as proof.

The real generator also ran in a fresh process with an empty HOME, outside the checkout, using this branch's source and the existing interpreter. It produced the exact catalog and created no commander configuration or bus. No runtime installation, saved-session modification, provider call or merge of this PR was performed.

Resource checker: /home/ts/bin/agent-resource-check is absent here; used the repository's tools/agent_resource_check.py --assert-headroom. Warnings only (3.3 GiB RAM available, 3.9 GiB /tmp free); tests were serial, bounded and reused installed dependencies. Disposable test output owned by pi-catalog was under /home/ts/.cache/agent-scratch/pi-catalog; removed after completion. Source and PR handoff stayed in /home/ts/wt/pi-catalog--P1.

Assumed:

  • P196 completes declarations and deterministic catalog generation, not the independent P197–P201 implementations.
  • “Sixth pattern” means a sixth seeded declaration; the branch already had nine additional patterns.
  • Seed numbers are external provenance, not runtime pattern identity; class objects own identity and heading strings are derived presentation.
  • Current main's commander owners take precedence over this stale branch's import-time migration.

trissim and others added 5 commits October 19, 2026 00:05
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
BehaviourPattern members name their signature in state, the existing checks
that enforce them (a StandingRule member, or a verb or tool refusal located
from source so the catalog never imports the commander verbs, which open
the installed bus), and where each was learned. docs/agents/behaviour-catalog.md
is BehaviourPattern.catalog(); the family test fails when they differ.

Src-Budget: 220

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…robes

Src-Budget: 260

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Src-Budget: 260
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 19, 2026 04:20

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

trissim and others added 9 commits October 19, 2026 00:31
….ProblemOrder

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every commander module bound CONFIG, ME, COMMS and path strings at import,
so importing commander/order.py read commander.json and opened the
installed bus. CommanderConfig.installed() already owns the installed
facts; it now also owns the bus (comms), the activity log, the forks
directory and the default review catch, and every use reads it when the
verb runs. The module globals, the order/capacity import cycle and the
test reloads that rebound them are deleted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Tests that read script.CONFIG, script.COMMS or judge.CONFIG read the
installed config; tests that replaced a module's CONFIG write the changed
config the way install does. strike takes who caught the miss
explicitly, and tool_watch now passes the struck task, which P194's
signature change had left as the reason.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
commander/order.py imports without opening the bus, so a refusal check
holds the function or class itself. The module and qualname strings,
the ast re-parse and the exists() probe it needed are deleted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each of the Codex postmortem's ten failures is a PostmortemFailure member
with its number and title; a pattern cites an instance, and the catalog
lists the declared members instead of range(1, 11).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…r incarnation

Functions that read the installed config more than once bind it at their
top. The commander's incarnation, read through the registry at 15 sites,
is a CommanderConfig property. Lines the longer reads pushed past 100
columns are wrapped, so the commander files carry the base's lint count.
The budget covers the catalog module (300 lines) and the commander
package's net 59.

Src-Budget: 359
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…atalog

# Conflicts:
#	src/agent_comms/commander/order.py
Seed patterns 1 (report instead of state, P198), 4 (wrong measure, P197),
15 (commander overloaded, P199), 16 (dead provider, P200) and 18 (unowned
work, P201) are members with their seed ID as a SeedCatalog source. Each
holds a PendingCheck naming the open problem whose change adds its check,
so those changes join an existing member.

Src-Budget: 419
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Remove the catalog's commander verb imports and cite the existing check owners directly. Derive postmortem coverage without a names roster. Keep the five seed declarations and distinguish their missing enforcement, including the two closed unmerged implementations. Verify regeneration without commander configuration and reject hand-edited output.
@trissim
trissim merged commit b76b58e into main Oct 19, 2026
0 of 4 checks passed
@trissim
trissim deleted the feat/p196-behaviour-catalog branch October 20, 2026 01:58
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.

2 participants