Skip to content

Schemas: the Role manifest, the pass record, the feed, and one envelope for all (#28) - #214

Merged
don-petry merged 2 commits into
mainfrom
claude/schemas-28-envelope
Oct 19, 2026
Merged

don-petry merged 2 commits into
mainfrom
claude/schemas-28-envelope

Conversation

@don-petry

@don-petry don-petry commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Why

Slice 0's exit asks for an example of every schema slice 1 uses. After #210 the pass record, the feed, a Run's applied.json and outcome.json, and the Role manifest had none, and §3.1's envelope rule, "every message carries schema, an identifier and the release", reached too far to hold as written. The working rulings on the issue, with the Maintainer's two answers folded in (applied.json and outcome.json are this story's fourth criterion; the feed carries the title, the next actor and the decision required), are the spec.

What is decided

One envelope, on what crosses a boundary whole (decision record 0039, provisional number). Each schema is in one class, held by ENVELOPE in tools/check_examples.py:

Class Carries Kinds
document schema, its identity, release task, result, applied, outcome (run); pass, view-meta, view-items (pass)
record schema facts, issue-facts, decision, issue-decision, finding
part nothing effect, disposition, coverage, run-name, run-record, view-item
data schema config, hooks, lifecycle, authority, apps, rubric, acceptance, trial, role, feed

config and hooks gain schema, and so do config/defaults.json, config/hooks.json and their counter-examples. Every reader of those files reads by key and ignores it.

What each schema holds, and what may not be written

Schema Holds May not hold
pass/1 now, the whole context (every key, always), every run record, each read's date and age, and per item its facts, Decision and the minted Run id. Its example is built by calling the Kernel and replays with the repo's own data files A title: the facts have no field for one (two new counter-examples). A copy of the configuration
view-meta/1, view-items/1, view-item The pass that wrote them; per item the Decision's codes, next_actor, decision_required, age, attempts, runs, cost, sources, url, and the title under untrusted Any other text; a title beside untrusted; a choice no person can make
feed/1, config/feed.json Who acts next, by outcome, then attention, then State; what is asked, one row per needs_you reason, a question and choices as codes A row for a reason the Kernel never gives needs_you, a reason twice, an attention class with no rule or two (_table)
applied/1, outcome/1 Each Effect apply met, with its state, the node id read back and a reason code, and each posted Finding's finding/1; how a Run ended, in the run record's codes A body; a state in words; a fault the design does not know
role/1 §3.11's manifest as JSON; each Intent's tier, permitted Effects, budget class and required eval set A kind or tier the design does not know; an Effect a Result cannot request

CODES_ONLY gains the new kinds and coverage; its one exemption, body, gains untrusted. The walk no longer follows a reference into a kind outside the set: the existing records are held by their own rules and are not swept here. tools/check_authority.py holds what a manifest owns, shadows and raises to finding/1's categories.

Where the rulings and the design differed, and the closed forms taken

  • A Decision and a Finding carry no id (the Decision) and no release (both): §3.4 and §3.7 amended.
  • The pass record's example replays with the repository's own config/defaults.json and Lifecycles, so its issue is not_served (issues are not served there); the pull request is admitted with its Run id.
  • attempts is a list of {intent, count}, not an object keyed by Intent: the validator cannot constrain a key.
  • next_actor lives in feed.schema.json#/$defs/actor, and view-item references it; by_outcome is its own list in config/feed.json.
  • The paused, pause_unreadable and unmerged_closes reasons are shown to need a person by the table test itself, beside the existing Kernel tests the check names.

Reviews

A fresh-context Claude review, a security pass (subagents) and Muse Wonder Full read the first head, 5109ac7; the Kernel and the simulator are untouched, so AGY was not run. Every finding was verified and folded into one fix round, 6fae96f:

  • config/feed.json matched no protected path, so a model-review-exempt change could rewrite what the Maintainer is asked (Muse's major; the security pass noted it). It joins the protected paths in config/hooks.json, as every other file in config/ does.
  • The codes-only walk stopped at a reference into run-record, so a pass record's run, role and intent were free strings (Muse's second major, the security pass's low). A run record holds codes now and joins CODES_ONLY. finding/1, which applied/1 carries, is the Factory's own record and stays as decision 0038 left it; the schema titles and the record now say so instead of claiming no text.
  • The untrusted exemption applied to any schema, and body exempted an object of strings (Claude). Only the feed marks text untrusted, and a body is one string; both have a test and a mutant.
  • A part could carry a release; a document's identity and release were not held to be strings (Claude, Muse, security). Both held, with mutants.
  • The table check let a State or an outcome be ruled twice (Claude, Muse, security). Refused now, and the feed test holds the table's rules to the design's: admit or act is the Factory's, then by class, then by State.
  • The manifest's categories in tools/check_authority.py had no test and no mutant (Claude, Muse). Added.
  • The replay test said every act mints a Run; only an approval does (Claude). Fixed.
  • config/hooks.json had been reformatted whole; it keeps its formatting with the one key added (Claude). The design's Decision and Finding examples validate against their schemas now (Claude).

Each of the twelve new mutants was applied by hand to a scratch copy and its named test seen to fail; CI's shards are the final word. Not taken, and recorded as waiting on roles/ or controller/: an owner with no App or an author that owns a category (the manifest's cross-field rules), a feed item whose url is not its item's, and an evidence alphabet beyond no-whitespace.

Verify

make verify passed on a fresh git archive export with PATH=/usr/bin:/bin SIM_SEEDS=40 at 6fae96f. (At 5109ac7 two timing tests of the identity hook ran over their 5-second bound while three reviews ran on the same machine; both pass alone and on the idle rerun.)

Closes #28

🤖 Generated with Claude Code

View guided diff Turn on auto-fix

don-petry and others added 2 commits October 19, 2026 16:33
…tcome, and one envelope for all (#28)

Each schema is in one class, held in ENVELOPE in tools/check_examples.py: a document carries
schema, its identity and release; a record or a data file schema alone; a part nothing. config
and hooks gain schema, with their files. Eight schemas: pass/1 (what replay needs, built by calling
the Kernel for its example), view-meta/1, view-items/1 and view-item (the feed, its one text the
title under untrusted, never in the facts), applied/1 and outcome/1 (a Run's artifacts), role/1
(the manifest of section 3.11) and feed/1 (config/feed.json: who acts next and what is asked, from
a Decision's codes, held to the Kernel's needs_you reasons). Seven tests, five mutants, decision
record 0039 (provisional number), rows in schemas/ and config/, and the design's sections 3.1,
3.4, 3.7, 3.10 and 8.4.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…nvelope reads types, and the exemptions are confined (#28)

One fix round from the reviews. config/feed.json joins the protected paths, as every file in
config/ is, so a change to it is reviewed by every model Lens. A run record's run, Role and Intent
are codes, and run-record joins CODES_ONLY, so a pass record is walked through it. A body is one
string, and only the feed marks text untrusted: an object of strings under either name in a Task
is caught. A part carries no release; a document's identity and release are strings. The table
check refuses a State or an outcome ruled twice, and the feed test holds the table's rules to the
design's. The manifest's categories have a test and a mutant. The replay test minted a Run for
every act; an approval is the one act that is a Run. config/hooks.json keeps its formatting. The
design's Decision and Finding examples validate.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@don-petry
don-petry requested a review from a team as a code owner October 19, 2026 21:59
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ⚠️ Failed 2026-10-19T21:59:46.476412Z 6fae96f PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@coderabbitai

coderabbitai Bot commented Oct 19, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 38 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Repository: combsmith/software-factory/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: da520714-301e-4246-b892-e3fa478c976c
📥 Commits

Reviewing files that changed from the base of the PR and between 233b22e and 6fae96f.

📒 Files selected for processing: 68
  • config/AGENTS.md
  • config/defaults.json
  • config/feed.json
  • config/hooks.json
  • docs/architecture/software-factory-design.md
  • docs/decisions/0039-one-envelope-on-what-crosses-a-boundary-whole.md
  • examples/applied.json
  • examples/applied.refused.json
  • examples/invalid/applied.an-effect-read-back-in-words.json
  • examples/invalid/applied.carries-the-comment-body.json
  • examples/invalid/applied.no-run.json
  • examples/invalid/config.a-change-by-a-person-skips-the-model-review.json
  • examples/invalid/config.a-neutral-check-passes.json
  • examples/invalid/config.a-required-lens-with-no-app.json
  • examples/invalid/config.a-required-lens-with-no-check.json
  • examples/invalid/config.a-required-lens-with-no-workflow.json
  • examples/invalid/config.a-staleness-limit-copied-from-the-lifecycle.json
  • examples/invalid/config.conclusion-mapped-to-nothing.json
  • examples/invalid/config.no-deterministic-lens.json
  • examples/invalid/facts.carries-the-title.json
  • examples/invalid/feed.a-choice-no-person-can-make.json
  • examples/invalid/feed.a-question-in-words.json
  • examples/invalid/hooks.a-lens-input-with-no-lens.json
  • examples/invalid/hooks.maintainer-with-no-email.json
  • examples/invalid/hooks.nothing-protected.json
  • examples/invalid/hooks.protected-path-that-climbs.json
  • examples/invalid/issue-facts.carries-the-title.json
  • examples/invalid/outcome.a-fault-the-design-does-not-know.json
  • examples/invalid/outcome.no-release.json
  • examples/invalid/outcome.sentence-as-reason.json
  • examples/invalid/pass.a-context-without-the-pause.json
  • examples/invalid/pass.a-decision-without-its-facts.json
  • examples/invalid/pass.a-run-id-in-another-form.json
  • examples/invalid/pass.no-release.json
  • examples/invalid/role.a-kind-the-design-does-not-know.json
  • examples/invalid/role.a-permitted-effect-a-result-cannot-request.json
  • examples/invalid/role.a-tier-the-engine-does-not-know.json
  • examples/invalid/role.an-intent-with-no-eval-set.json
  • examples/invalid/view-items.a-choice-no-person-can-make.json
  • examples/invalid/view-items.a-next-actor-in-words.json
  • examples/invalid/view-items.a-title-not-marked-untrusted.json
  • examples/invalid/view-items.no-release.json
  • examples/invalid/view-items.sentence-as-reason.json
  • examples/invalid/view-meta.no-pass.json
  • examples/invalid/view-meta.time-in-another-format.json
  • examples/outcome.json
  • examples/pass.json
  • examples/role.json
  • examples/role.owner.json
  • examples/view-item.json
  • examples/view-items.json
  • examples/view-meta.json
  • schemas/AGENTS.md
  • schemas/applied.schema.json
  • schemas/config.schema.json
  • schemas/feed.schema.json
  • schemas/hooks.schema.json
  • schemas/outcome.schema.json
  • schemas/pass.schema.json
  • schemas/role.schema.json
  • schemas/run-record.schema.json
  • schemas/view-item.schema.json
  • schemas/view-items.schema.json
  • schemas/view-meta.schema.json
  • tests/test_tools.py
  • tools/check_authority.py
  • tools/check_examples.py
  • tools/mutants.py
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@sonarqubecloud

Copy link
Copy Markdown

@don-petry
don-petry added this pull request to the merge queue Oct 19, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Oct 19, 2026
@don-petry
don-petry added this pull request to the merge queue Oct 19, 2026
Merged via the queue into main with commit ba4e76e Oct 19, 2026
16 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.

Schemas for the Role manifest, the pass record and the feed; and one envelope for all

1 participant