Skip to content

Adopt the aos workflow and state the repository rules for agents - #2

Merged
kschlt merged 2 commits into
mainfrom
claude/project-thread-82nj9p-aos
Sep 22, 2026
Merged

kschlt merged 2 commits into
mainfrom
claude/project-thread-82nj9p-aos

Conversation

@claude

@claude claude Bot commented Sep 22, 2026 •

Copy link
Copy Markdown

Before: work on earnedshape had no shared backlog, commit or PR workflow, and the repository held no written rules for agents working in it.

After: tool and backlog work runs through aos, the author's own backlog, commit, PR and review workflow, and every agent working here reads the repository rules from CLAUDE.md.

This PR adds only the host-side wiring: aos keeps its instance state in a separate private repository, so nothing private lands here when this repository goes public.

How: the aos scaffold was run with this project's own commands (the boundary lint as the quality, test and lint gate; no formatter; prose commit subjects; test-first off because there is no test suite). It wrote the two managed regions, the CLAUDE.md pointer and the .aos ignore line. Two hand additions sit outside them: a .claude ignore line, and a short "earnedshape" section in CLAUDE.md with the agent rules.

Merge after #1 (see Risks).

Why

The owner wants all future tool and backlog work on earnedshape to go through aos, with the instance state kept outside this repository so it stays clean for publication. Backlog item AOS.

Approach

  • Host footprint kept minimal. The host carries only the aos managed regions plus two hand additions; everything else lives under the ignored .aos/.
  • .claude is ignored, not tracked. The local .claude symlink points into the untracked aos machinery clone, so tracking it would leave a dangling link for anyone cloning this repository.
  • Repository rules live in the public CLAUDE.md. The rules (public-facing repository, vendor-free protocol/, no private or employer-related content, own projects only with a one-line description, spike code stays private, research claims cite research/REFERENCES.md) could have lived only in the private instance. They sit here instead because every agent working on the repository needs them and they contain nothing sensitive.

Acceptance List

Derived from the acceptance criteria of AOS.

  • freshness.py start reports green for the instance — proof: eval:freshness-start (python3 .aos/sys/core/scripts/freshness.py start) — Verify: run python3 .aos/sys/core/scripts/freshness.py start in a checkout with the aos instance mounted; it exits 0. It only warns on a missing region, so also check that CLAUDE.md carries aos:begin id=task-workflow and .gitignore carries aos:begin id=host-ignore
  • The host diff against main contains only the aos managed regions, a .claude ignore line, and a short repository-rules section in CLAUDE.md for agents working on the public repository (public-facing, vendor-free protocol/, no private or employer-related content, own projects only with a description, spike code stays private, claims cite REFERENCES.md) — proof: eval:host-diff-managed-regions-only (git diff main --stat and inspection of the hunks) — Verify: the diff touches only .gitignore (+10) and CLAUDE.md (new, 12 lines); read both hunks: one aos:begin/aos:end region per file, the .claude line, and the # earnedshape section with its four rules
  • The boundary lint exits 0 — proof: boundary-lint (python3 tools/boundary_lint.py .) — Verify: run python3 tools/boundary_lint.py .; it reports 2 findings, 0 new, and exits 0
  • Nothing under .aos/ or the .claude symlink is tracked by this repository — Verify: git ls-files .aos .claude prints nothing on this branch

What Was Tested

  • python3 tools/boundary_lint.py . reports 2 findings, 0 new: the published baseline is unchanged.
  • python3 .aos/sys/core/scripts/freshness.py start exits 0 against the mounted instance.
  • The full suite gate passed on the item's IN_PROGRESS to IMPLEMENTED transition.
  • git ls-files .aos .claude is empty, so no instance state or machinery link is tracked.

Risks

🤖 Generated with Claude Code

https://claude.ai/code/session_01Kkcu5mQ2JpAcSWUwskrSJw

Future tool work on earnedshape runs through aos, the author's own
backlog and commit/PR workflow layer. Its machinery and instance state
live under .aos/, which is ignored here: the instance keeps its own
history in a separate private state repository, so this commit carries
only the host-side changes.

The aos scaffold wrote the two managed regions: the task-workflow
pointer at the top of CLAUDE.md and the .aos ignore line. It was run
with this project's own commands: the boundary lint is the quality,
test and lint gate, no formatter is declared, commit subjects stay plain
prose to match the existing history, and test-first is off because
there is no test suite.

Two additions sit outside the managed regions:

- A .claude ignore line. The .claude symlink points into the untracked
  machinery clone, so tracking it would leave a dangling link for anyone
  cloning this repository.
- An "earnedshape" section in CLAUDE.md with the rules any agent working
  here must follow: the repository is public-facing; protocol/ stays
  vendor-free, enforced by tools/boundary_lint.py; nothing private,
  personal, employer- or client-related, and no discovery-run content;
  the author's own projects only with a one-line description; spike code
  stays in the private working repository; research claims cite
  research/REFERENCES.md. These rules live in the public repository
  rather than only in the private instance because every agent working
  here needs them and they contain nothing sensitive.

Checked: python3 tools/boundary_lint.py . reports 2 findings, 0 new,
so the published baseline is unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kkcu5mQ2JpAcSWUwskrSJw
@claude
claude Bot requested a review from kschlt September 22, 2026 20:57
@claude claude Bot assigned kschlt Sep 22, 2026
@claude

claude Bot commented Sep 22, 2026

Copy link
Copy Markdown
Author

PR Review Verdict

Result: BLOCK

Deterministic: boundary-lint CI check run on the PR head: success (both the push and pull_request runs); locally python3 tools/boundary_lint.py . reports 2 finding(s), 0 new, exit 0 — Tree: kschlt/earnedshape (the PR's own tree; commands.quality) — Head: 0a97d86

Acceptance Criteria

  • [met] freshness.py start reports green for the instance — Evidence: ran it in a checkout of the head with the instance mounted: exit 0, fetches ok, state pull up to date, no managed-region warnings; its one warning concerns unpushed instance state commits, which is instance-side and not about this diff. Green here is read from the output, not the exit code (see the first advisory finding)
  • [met] The host diff against main contains only the aos managed regions, a .claude ignore line, and the short repository-rules section in CLAUDE.md — Evidence: git diff main..head --stat shows only .gitignore (+10) and a new CLAUDE.md (12 lines); one aos:begin/aos:end region per file, the .claude line, and the # earnedshape section with its four rules. The machinery's region checker reports both text regions present, markers intact, rev matching
  • [met] The boundary lint exits 0 — Evidence: CI green on the head; local run 2 findings, 0 new, exit 0. The vendor rule reads only protocol/, and the new CLAUDE.md is in scope only for the CAP-reference rule (it has no CAP references). So the lint shows the diff does not break the gate, not that the diff's content is correct
  • [met] Nothing under .aos/ or the .claude symlink is tracked by this repository — Evidence: git ls-tree -r of the head lists nothing under either path; with both mounted as symlinks in a head checkout, git status is clean and git check-ignore -v attributes them to .gitignore:12 (.aos) and .gitignore:6 (.claude)

Findings

  • [blocking][reproduced] The PR body states that this PR is independent of Make the repository ready to publish: checked sources, review record, provenance #1 and "either can merge first", but the new CLAUDE.md sends agents to docs/provenance.md, docs/phase-1-feasibility.md and research/REFERENCES.md, and none of the three exists on main or on this head; they exist only on Make the repository ready to publish: checked sources, review record, provenance #1's branch. Merged first, main carries agent rules that point at missing files, including the rule that every research claim cites research/REFERENCES.md. Fix: state in the body that Make the repository ready to publish: checked sources, review record, provenance #1 must merge first (or rebase onto it), or reword the three references so they do not depend on Make the repository ready to publish: checked sources, review record, provenance #1
  • [advisory][reproduced] The Verify step for criterion 1 ("it exits 0") does not discriminate: freshness.py start reports managed-region integrity as warnings only and exits 0 without them. Run on main, which has no CLAUDE.md region and a stale .gitignore, it still exits 0 and prints two region-integrity warnings. The criterion ("reports green") holds on the head only because the output has no region warnings, not because of the exit status
  • [advisory][reasoned] The acceptance criterion that allows the CLAUDE.md rules section was amended on the same day, shortly before the PR opened, so that it matches the diff. The amendment says it supersedes the earlier wording. This review cannot tell whether the owner asked for the widening or the implementing session made it, and the human merging should confirm it

Not Checked

Routed

  • The machinery's touchpoint.py check reports the registered .mcp.json region (mcp-servers, empty owned) as FAIL on this correctly adopted host and exits 1, while freshness.py treats an empty-owned JSON region's absence as the correct state. The two readers of one registry disagree about the same host — Landing zone: .aos/input/ of the machinery instance (machinery report, provenance envelope with machinery SHA 1306faf attached, draft returned with this verdict) — Filing: outstanding
  • The scaffold creates the host .claude symlink into the machinery clone, but the host-ignore managed region ignores only .aos, so every consumer has to hand-add an unmanaged .claude ignore line, as this PR does — Landing zone: .aos/input/ of the machinery instance (machinery report, provenance envelope with machinery SHA 1306faf attached, draft returned with this verdict) — Filing: outstanding

Judgment Dimensions

  • Code smell: none introduced.
  • Complexity: none added: 22 additive lines, no code.
  • Need-to-build: the two managed regions come from the existing scaffold writer, and nothing was rebuilt. The hand-added .claude ignore line fills a gap the machinery leaves (see Routed).
  • Condensed better, not worse: yes, once the merge order is fixed. The host gets a minimal, documented footprint and explicit agent rules.

Generated by Claude Code

@claude

claude Bot commented Sep 22, 2026

Copy link
Copy Markdown
Author

Review round 1, how each finding was handled:


Generated by Claude Code

@claude

claude Bot commented Sep 22, 2026

Copy link
Copy Markdown
Author

PR Review Verdict

Result: PASS

Deterministic: boundary-lint CI lint check runs on the PR head: success (both runs); locally python3 tools/boundary_lint.py . on the head tree reports 2 finding(s), 0 new, exit 0 — Tree: kschlt/earnedshape (the PR's own tree; commands.quality) — Head: 0a97d86

Acceptance Criteria

  • [met] freshness.py start reports green for the instance — Evidence: round 2 checks the amended Verify step: CLAUDE.md carries aos:begin id=task-workflow and .gitignore carries aos:begin id=host-ignore on the head (1 hit each), and neither marker exists on main (0 hits each). The added check fails when the region is missing, which the exit status alone did not. A region with its end marker deleted would still pass this check, but criterion 2's reading of the hunks catches that. freshness.py start was not re-run because the head has not changed since round 1, which saw exit 0 with no region warnings
  • [met] The host diff against main contains only the aos managed regions, a .claude ignore line, and the short repository-rules section in CLAUDE.md — Evidence: the head has not changed. The diff still touches only .gitignore (+10) and a new CLAUDE.md (12 lines). The three files the rules point at (docs/provenance.md, docs/phase-1-feasibility.md, research/REFERENCES.md) exist on Make the repository ready to publish: checked sources, review record, provenance #1's current head and are all absent from main. docs/provenance.md there names the author's own projects with one-line descriptions, docs/phase-1-feasibility.md records spike status, and research/REFERENCES.md marks fields it could not check (spelling: see the advisory finding)
  • [met] The boundary lint exits 0 — Evidence: CI green on the head, and the local run on the head tree gives 2 findings, 0 new, exit 0
  • [met] Nothing under .aos/ or the .claude symlink is tracked by this repository — Evidence: the head has not changed, and the diff adds no path under either. Round 1's git ls-tree evidence still holds

Findings

Not Checked

Routed

Judgment Dimensions

  • Code smell: none. The delta is the PR body and a backlog dependency, with no code change.
  • Complexity: not applicable, because the head is unchanged.
  • Need-to-build: not applicable, for the same reason. The ordering uses the existing backlog dependency mechanism rather than anything new.
  • Condensed better, not worse: yes. The body now states the merge order and why. It is accurate: the two PRs share no file, and the three files the rules point at exist only on Make the repository ready to publish: checked sources, review record, provenance #1. Criterion 1 can now fail on a missing region.

Generated by Claude Code

The CLAUDE.md rule said a source field that could not be checked "stays
marked as unchecked", while research/REFERENCES.md marks such fields
"not confirmed" with a reason, and the publication PR's acceptance check
searches for exactly that phrase. An agent following the rule literally
would write a marker the check does not find (advisory finding, review
round 2).

The rule now says such a field stays marked "not confirmed", with the
reason: the convention REFERENCES.md already uses. The edit is one line,
outside the aos managed region.

Tested: python3 tools/boundary_lint.py . reports 2 findings, 0 new.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kkcu5mQ2JpAcSWUwskrSJw
@claude

claude Bot commented Sep 22, 2026

Copy link
Copy Markdown
Author

Review round 2 (PASS): the one advisory is fixed in 78578d5. The CLAUDE.md rule now says an unchecked field stays marked "not confirmed", with the reason. That is the marker REFERENCES.md uses, and it is the phrase #1's acceptance check searches for.


Generated by Claude Code

@claude

claude Bot commented Sep 22, 2026

Copy link
Copy Markdown
Author

PR Review Verdict

Result: PASS

Deterministic: boundary-lint CI lint check runs on the PR head: success (both runs); locally python3 tools/boundary_lint.py . on the head tree reports 2 finding(s), 0 new, exit 0 — Tree: kschlt/earnedshape (the PR's own tree; commands.quality) — Head: 78578d5

Acceptance Criteria

  • [met] freshness.py start reports green for the instance — Evidence: the delta (78578d5) changes one line of CLAUDE.md, outside the aos managed region. The amended Verify step still holds on the head: CLAUDE.md carries aos:begin id=task-workflow and .gitignore carries aos:begin id=host-ignore (1 hit each). freshness.py start was not re-run this round (see Not Checked)
  • [met] The host diff against main contains only the aos managed regions, a .claude ignore line, and the short repository-rules section in CLAUDE.md — Evidence: git diff main..head --stat still shows only .gitignore (+10) and a new CLAUDE.md (12 lines, 1 insertion and 1 deletion in the delta). The changed line is the fourth rule of the # earnedshape section, and it now says an unchecked field stays marked "not confirmed", with the reason. That matches research/REFERENCES.md on Make the repository ready to publish: checked sources, review record, provenance #1's head (4042305): 10 hits for "not confirmed", each carrying a reason, and no use of "unchecked". It also matches the phrase Make the repository ready to publish: checked sources, review record, provenance #1's acceptance check searches for
  • [met] The boundary lint exits 0 — Evidence: both CI lint runs on 78578d5 concluded success; the local run on the head tree gives 2 findings, 0 new, exit 0
  • [met] Nothing under .aos/ or the .claude symlink is tracked by this repository — Evidence: git ls-files .aos .claude prints nothing on the head, and git ls-tree -r of the head lists no path under either

Findings

Not Checked

Routed

Judgment Dimensions

  • Code smell: none. The delta is one line of prose.
  • Complexity: none added. The line count of CLAUDE.md is unchanged.
  • Need-to-build: not applicable. The rule now uses the marker research/REFERENCES.md already uses instead of adding a second one.
  • Condensed better, not worse: yes. The rule and the repository convention now use one marker, so an agent following the rule writes what Make the repository ready to publish: checked sources, review record, provenance #1's check looks for.

Generated by Claude Code

@kschlt
kschlt merged commit f0c9dce into main Sep 22, 2026
2 checks passed
@kschlt
kschlt deleted the claude/project-thread-82nj9p-aos branch September 22, 2026 21:49
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