Skip to content

feat(org): intake — route work before anything is written - #269

Merged
itsHabib merged 10 commits into
mainfrom
feat/org-intake
Aug 29, 2026
Merged

feat(org): intake — route work before anything is written#269
itsHabib merged 10 commits into
mainfrom
feat/org-intake

Conversation

@itsHabib

Copy link
Copy Markdown
Owner

Summary

Closes the field report's headline gap (§4.1): there was no intake path — two agents spent an hour registering zero work. org intake -work <uri> answers, read-only, which chartered lanes could hold a work URI and precisely what is missing if none can.

What this adds

  • contracts/org.InScope / MatchScope — the scope-membership predicate the skills already claimed existed ("a mechanical predicate, never a judgment call") but the kernel never enforced (§4.4, proven twice). Prefix-at-a-boundary; never across schemes (§4.5's rule); explicit open-prefix entries (jira:PROJ-, github:owner/, jira:) state a charter's grain without glob syntax. A pure leaf function: intake reads it today, assign can enforce it later (scope_mismatch is the next slate item).
  • org intake -work <uri> [-json] — for each live lane in the tenant: in scope (which entry), already holds it (an out-of-scope hold renders as "holds it OUT OF SCOPE" — §4.4's drift, surfaced instead of silent), unreadable chains named rather than skipped. When nothing covers the URI: the fact plus the fix (charter or recharter). Exit 0 — it is a report; safe to make the reflex.
  • Guide pair (CLAUDE.md/AGENTS.md, byte-identical), README, and usage text updated.

Validation

gofmt -l ./cmd/org ./contracts/org   # clean
go vet ./cmd/org/... ./contracts/org/...
golangci-lint run ./cmd/org/... ./contracts/org/...   # 0 issues
go test ./cmd/org/... ./contracts/org/...   # all ok, incl. TestIntakeRoutesWork end-to-end + predicate table

Stacked on #266 (shares cmd/org/main.go); retarget to its base when the train advances.

🤖 Generated with Claude Code

itsHabib and others added 7 commits August 24, 2026 21:50
The substrate is a bet: that a session leaves something the next one can
inherit. Nothing measured it. `org sweep` does, from the chains alone,
with no cooperation from any agent.

It REPLAYS each chain through the kernel rather than scanning kinds,
because the number that matters is invisible to a scan: a takeover's
record does not name the claim it stranded, so an orphaned obligation is
only visible as a fold transition. The sweep counts orphans, and how
many a successor then discharged.

The headline pair: distilled session ends (a checkpoint — a real
conclusion) against ones only observed (a mark), and inherited
obligations discharged against orphaned. A rate with no data renders as
an em dash, never 0% — "no session has ended yet" and "every session
ended undistilled" are the two findings that must never share a value.
A chain that stops folding is a BROKEN row carrying the counts from
before the break, not a failed sweep.

Exposed over MCP as org_sweep (read-only, so it joins the allowlist).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…see it

Two related findings from review round 1, both about the same gap: the
sweep claimed to preserve what a chain recorded before a break, and
neither path actually delivered it.

survey.Of returned early on a refused record without carrying the state
that DID fold, so a BROKEN row reported no dangling work and Sum's
counter undercounted — a chain could strand an obligation and the
aggregate would say zero. Both exits now go through one withState, so
the broken and healthy paths cannot report different fields.

cmdSweep read through Load, which folds internally and is all-or-nothing:
a chain that stopped folding arrived empty, so the CLI reported zero
records for exactly the chain worth looking at. It now reads records via
the new home.Records and lets the replay decide admissibility.

Tests pin both, plus the revoke-while-active orphan path the review
flagged as untested — revoke reaches the same kernel orphan() as
takeover through a different transition, and "high confidence by
inspection" is how the untested arm of a pair diverges.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Round-2 finding: LastAt was stamped from the tip after the loop, so the
early return on a refused record left it empty — a BROKEN row exists to
be diagnosed from, and a reader cannot diagnose a chain that will not
say when it was last valid. It is now stamped per folded record, which
is the only place it can come from: state carries no timestamp, so
withState cannot recover it afterwards.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…g is written

The first live multi-lane run's headline gap (field report §4.1): two
agents, one hour, zero work registered — every minute spent discovering
routing facts the substrate could have answered. org intake answers them
read-only: which chartered lanes' scopes cover a work URI, which lanes
already hold it (an out-of-scope hold renders as drift, §4.4's proven
gap), and when nothing covers it, that fact plus the fix.

The membership predicate the skills already claimed — 'a mechanical
predicate, never a judgment call' — now exists: contracts/org.InScope,
prefix-at-a-boundary, never across schemes (§4.5's rule), with explicit
open-prefix entries (jira:PROJ-, github:owner/, jira:) stating a
charter's grain. assign can enforce it later; intake reads it today.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@itsHabib

Copy link
Copy Markdown
Owner Author

@claude please review this PR and publish your findings as a FORMAL GitHub review pinned to head 802b9e1 — not only a comment. Focus: the InScope predicate's boundary rules (contracts/org/scope.go) against field report §4.4/§4.5, the read-only guarantee of the intake verb, and the guide-pair sync.

@itsHabib

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Aug 29, 2026

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 Completed 2026-08-29T06:07:16.890614Z 4d54a91 Manual request
ℹ️ 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.

@claude

claude Bot commented Aug 29, 2026

Copy link
Copy Markdown

Claude finished @itsHabib's task in 5m 0s —— View job


PR #269 Review — feat(org): intake

Reviewed head: 802b9e1f041dcdcda952e6d4a4c3d5786cf14e7b

  • Read changed files
  • Analyze InScope predicate boundary rules (§4.4/§4.5)
  • Verify read-only guarantee of intake verb
  • Verify guide-pair sync (CLAUDE.md / AGENTS.md byte-identical)
  • Post formal GitHub review

Formal review posted as a PR review comment. Findings summary:

No P1 issues. The implementation is correct on all three focus areas.

InScope predicate (§4.4/§4.5):

  • Cross-scheme exclusion (§4.5) is structurally guaranteed by strings.HasPrefix — no entry can match across schemes.
  • Drift surfacing (§4.4): intakeLane independently checks MatchScope and state.Held, so a lane holding work out of scope appears as "holds it OUT OF SCOPE" in the report, not silently.
  • The openPrefix / boundary asymmetry for '-' is correct and tested.
  • P2: scope_test.go covers '/', ':', '-' as open-prefix characters in entries but not '#'. Two cases would complete the table ({"github:owner/repo#", "github:owner/repo#88", true} and the negative). Worth closing before assign enforces this predicate.

Read-only guarantee: cmdIntake only calls h.RolesForTenant + h.Load. h.Append is never reached. Exit 0 on all successful report paths — the invariant holds.

Guide-pair sync: diff cmd/org/CLAUDE.md cmd/org/AGENTS.md → empty. Byte-identical, blob SHA match confirmed. ✓

P3s (non-blocking): JSON "phase":"" on unreadable chains is ambiguous with PhaseVoid; PhaseVoid exclusion in intakeLane is implicit rather than guarded; newScope adds unused -role/-strict/-incarnation flags to intake.

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 802b9e1f04

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +42 to +46
if in.Covered {
return sb.String()
}
fmt.Fprintf(&sb, "no chartered scope covers %s\n", in.Work)
sb.WriteString("fix: charter a lane whose -scope covers it, or recharter an existing lane\n")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Handle unreadable lanes before declaring no coverage

When a role directory contains a corrupt or unreadable chain and no readable lane matches, intakeLane retains the error row but leaves Covered false, so this renderer definitively says that no chartered scope covers the work and recommends creating or rechartering a lane. The unreadable chain may be the covering owner, so following that advice can create a competing lane; represent the result as indeterminate and suppress the no-coverage conclusion until every lane has been judged.

AGENTS.md reference: cmd/org/AGENTS.md:L33-L38

Useful? React with 👍 / 👎.

Comment thread contracts/org/scope.go
Comment on lines +10 to +12
// `github:owner/repository`. An entry that itself ends in a separator is an
// explicit open prefix — `jira:PROJ-` covers a project, `github:owner/` an
// owner, `jira:` a whole scheme — which is how a charter states its grain

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Make advertised scheme-wide scopes charterable

The advertised jira: whole-scheme scope cannot be used by org intake: the existing workURIPattern in contracts/org/validate.go requires at least one non-whitespace character after the colon, and the JSON schema has the same restriction, so org charter -scope jira: is refused as malformed. Align charter/schema validation with this newly supported open-prefix form, or remove the unreachable scheme-wide behavior and documentation.

Useful? React with 👍 / 👎.

@claude claude Bot 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.

Reviewed head: 802b9e1

InScope predicate — contracts/org/scope.go

The implementation is correct on both §4.4 and §4.5.

§4.5 (never cross schemes): Enforced structurally by strings.HasPrefix. Any entry whose scheme prefix differs from the work URI's scheme prefix fails the prefix check at the first byte divergence. No explicit scheme guard is needed and none would add safety. ✓

§4.4 (drift surfaced, not silenced): intakeLane in cmd/org/main.go:541 calls MatchScope and then separately scans state.Held. A lane that holds the work but whose scope doesn't match it returns ScopeMatch="" + Holds=true — the keep=true path — and laneNote renders it as "holds it OUT OF SCOPE". The field-report failure mode (silent acceptance into a mismatched lane) becomes a visible row in the report. ✓

The openPrefix / boundary asymmetry (contracts/org/scope.go:26-32) is correct and load-bearing: '-' appears in openPrefix (so jira:PROJ- is an explicit open prefix) but NOT in boundary (so github:owner/my does not cover github:owner/my-repo — the character after the entry is '-', which fails the boundary check). The test at scope_test.go:17 ({"github:owner/my", "github:owner/my-repo", false}) pins this. ✓

P2 — Missing # open-prefix test in scope_test.go:
The four open-prefix characters are '/', '#', ':', '-'. Tests cover entries ending in '/' ("github:owner/"), ':' ("jira:"), and '-' ("jira:PROJ-"), but not '#'. A case like:

{"github:owner/repo#", "github:owner/repo#88", true},
{"github:owner/repo#", "github:owner/repo/path", false},

would complete the coverage for all four open-prefix characters. The logic is identical to the / path, so this is a coverage gap rather than a bug, but the field report §4.4 specifically names # as a structural boundary character that must work correctly. Fix this →

P3 — JSON output for unreadable chains has "phase": "":
When h.Load fails inside intakeLane (main.go:543), lane.Phase stays as the zero value (""), which is PhaseVoid. The "error" field signals the condition, but a machine consumer inspecting "phase" sees "" (void) rather than something that indicates "unknown due to read error." The Err field is the correct signal — this is a documentation clarity gap, not a bug — but adding omitempty to Phase in IntakeLane (render/intake.go:15) would make the signal unambiguous: a missing phase key means the chain was unreadable.

P3 — PhaseVoid exclusion is implicit rather than guarded:
intakeLane (main.go:549) explicitly guards PhaseRetired. Void chains are correctly excluded too — MatchScope(nil, work) returns ("", false) and empty held list yields keep=false — but this relies on emergent behavior rather than an explicit check. A one-line guard if state.Phase == org.PhaseVoid { return lane, false } (or a comment) would make the intent legible to a future reader of the phase-filtering logic.


Read-only guarantee — cmdIntake

cmdIntake (main.go:507-537) calls h.RolesForTenant and, inside intakeLane, h.Load only. Neither call is a write path. h.Append is never invoked. The lock acquired by home.Open is not held in read-only callers — s.open(args, false) confirms no role is required and no write is attempted.

Exit code is always 0 on a successful report, regardless of whether any lane covers the URI (in.Covered is a field in the output, not an exit signal). This makes intake safe as a reflex — exit 0 is the invariant. The test at main_test.go:378 confirms it. ✓

P3 — newScope adds unused flags to intake:
cmdIntake calls newScope("intake"), which registers -incarnation, -strict, -role, and -json flags. The -json flag is consumed. The others are accepted but have no effect (no write path, no role-scoping). A user who passes -role lead:foo would get the full-tenant report, not a narrowed one. This is not a bug but could surprise a caller. A usage note or explicit rejection of -role for intake would be cleaner, though the current behavior is safe.


Guide-pair sync

cmd/org/CLAUDE.md and cmd/org/AGENTS.md carry the same blob SHA (ba6304122ed166f8838b27c7e5389ac503db23e2) in the changed-files listing, and diff cmd/org/CLAUDE.md cmd/org/AGENTS.md returns empty. Byte-identical. Both include the intake verb description and read-only characterization. CI's guide-pair sync requirement is satisfied. ✓

The intake entry in both guides ("Read-only; safe to run on sight of new work") matches the implementation's exit-0 contract.


Summary

No P1 issues found. The InScope predicate correctly enforces both §4.4 drift-surfacing and §4.5 cross-scheme exclusion. The read-only guarantee holds at the call-site level. Guide-pair is byte-identical.

Residual items: one P2 (missing # open-prefix test covering all four boundary characters), two P3s (JSON phase zero-value for error lanes; implicit PhaseVoid exclusion). None of these block the merge — the first is the most worth closing before assign enforces this predicate in the next slate item.

…unreadable lanes

- contracts/org: scope entries validate against scopeEntryPattern (the
  remainder optional) so the advertised bare-scheme grain (jira:) is
  actually charterable; Subject work URIs keep the strict pattern.
- intake render: an uncovered report with unreadable lanes hedges ('no
  READABLE chartered scope … N lane(s) unreadable') instead of concluding
  nothing covers the work; phase omits from JSON when a chain was
  unreadable; PhaseVoid excluded explicitly.
- tests: all four open-prefix boundary chars, bare-scheme charter
  end-to-end, and the unreadable-lane hedge.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@itsHabib

Copy link
Copy Markdown
Owner Author

@codex review

Round-1 fold pinned to 5c091758. Both P2s fixed: scope entries now validate against a dedicated scopeEntryPattern (bare-scheme grain charterable; subject work URIs unchanged), and an uncovered report with unreadable lanes hedges instead of concluding. Claude's P2 (# boundary test) and both P3s (phase omitempty, explicit PhaseVoid guard) also landed. The unused-flags note (-role accepted but ignored on intake) is deferred as a P3 nit — every read verb shares newScope.

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5c091758b8

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread contracts/org/validate.go
}
for i, s := range r.Terms.Scope {
if !workURIPattern.MatchString(s) {
if !scopeEntryPattern.MatchString(s) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Align the schema with bare-scheme scope admission

The fresh folded tree changes Go admission to accept jira:, but contracts/org/schema/org-record-v1.json line 59 still requires \S+ after the colon. Consequently, a charter emitted successfully by this CLI is invalid according to the embedded schema consumed by non-Go implementations. Update the scope item's schema pattern—and add it to the pattern conformance test—so both contract representations accept the advertised scheme-wide scope.

AGENTS.md reference: AGENTS.md:L19-L22

Useful? React with 👍 / 👎.

Comment thread cmd/org/main.go
Comment on lines +514 to +515
if *work == "" {
return fmt.Errorf("-work is required")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reject malformed intake work URIs

When a scheme-wide scope exists, inputs such as org intake -work 'jira: bad' pass this nonempty-only check and are reported as covered because InScope("jira:", ...) accepts every matching prefix, even though assign later refuses the same value under workURIPattern. Validate -work with the subject-work grammar before routing so intake cannot recommend a lane for work that the system cannot record.

AGENTS.md reference: cmd/org/AGENTS.md:L33-L38

Useful? React with 👍 / 👎.

…uses unrecordable URIs

- contracts/org/schema: the scope item pattern gains the optional
  remainder, matching Go admission; the pattern conformance test now
  covers the scope grammar so the two representations cannot drift again.
- intake validates -work against the subject-work grammar (exported as
  org.ValidWorkURI) before routing — it never recommends a lane for work
  the kernel could not record.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@itsHabib

Copy link
Copy Markdown
Owner Author

@codex review

Round-2 fold pinned to e18a0b6. Both round-2 P2s fixed: the schema's scope pattern now agrees with Go admission (and the pattern conformance test covers the scope grammar so they cannot drift again), and intake validates -work against the subject-work grammar (org.ValidWorkURI) before routing. Per review-cycle discipline this is the final panel round on this PR — residuals go to the judge.

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e18a0b6d05

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +144 to +146
{"scope", s.child(t, "terms").child(t, "scope").Items.Pattern,
[]string{"github:acme/api", "jira:PROJ-", "jira:"},
[]string{"PROJ-412", "jira: bad", ""}},

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Exercise the schema regex in the conformance test

The new scope case reads tc.pattern but uses it only in failure messages; both loops execute only the Go matcher returned by goPattern. Consequently, changing the schema back from \S* to \S+—or to any unrelated pattern—leaves this test green while Go and non-Go consumers disagree about whether jira: is valid. Compile and execute the schema pattern against the same cases, then compare its result with Go admission.

AGENTS.md reference: AGENTS.md:L19-L22

Useful? React with 👍 / 👎.

type Intake struct {
Work string `json:"work"`
Tenant string `json:"tenant"`
Covered bool `json:"covered"`

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Represent unreadable intake results as indeterminate in JSON

When every readable lane misses but one chain is unreadable, -json still emits "covered": false. Fresh evidence in this fold is that the JSON branch returns this struct before IntakeText, so the new human-readable hedge never reaches machine callers. A caller routing on covered can therefore interpret an unjudged result as confirmed uncovered and charter a competing lane; make coverage tri-state or expose an explicit completeness/indeterminate field.

AGENTS.md reference: cmd/org/AGENTS.md:L33-L38

Useful? React with 👍 / 👎.

@itsHabib

Copy link
Copy Markdown
Owner Author

Round cap reached — recording the final round's two P2s as deferrals for the judge rather than a fourth panel round:

  1. Conformance test doesn't execute the schema regex (contracts/org/conformance_test.go): the scope case exercises the Go matcher; the schema pattern string is only compared indirectly. Deferred: the pre-existing test harness has this shape for every grammar (role, incarnation, work), not just the new scope case — fixing it is a harness change that belongs in its own commit on the next slate PR, applied to all four cases at once.
  2. JSON covered is binary while unreadable lanes exist (render/intake.go): the text report hedges; the JSON should carry an indeterminate marker. Deferred: additive JSON field (indeterminate or unreadable_lanes count), no consumer exists yet; queued for the next slate PR alongside the scope_mismatch work that will consume this JSON.

Both are queued for the transfer/scope_mismatch slate PR.

@itsHabib

Copy link
Copy Markdown
Owner Author

@claude please review this PR and publish your findings as a FORMAL GitHub review pinned to head e18a0b6f0c25514ca29632086463aabb42a94dd0 — not only a comment. The two known residual P2s are recorded as deferrals in the comment above; verify the round-2 fixes (schema/Go scope-pattern agreement + conformance coverage, intake's ValidWorkURI guard) and flag anything new at P1.

@claude

claude Bot commented Aug 29, 2026

Copy link
Copy Markdown

Claude finished @itsHabib's task in 3m 53s —— View job


PR #269 Review — Round-2 fold verification

Reviewed head: e18a0b6f0c25514ca29632086463aabb42a94dd0

  • Read changed files at HEAD
  • Verify fix 1: schema/Go scope-pattern agreement + conformance test coverage
  • Verify fix 2: intake ValidWorkURI guard
  • Scan for new P1 issues — none found
  • Post formal GitHub review

Formal review posted. Summary:

Fix 1 verified — schema/Go scope-pattern agreement:

  • scopeEntryPattern (validate.go:30) uses \S* — bare-scheme entries (jira:) admitted
  • JSON schema (org-record-v1.json:59) pattern \S* — the two agree character-for-character
  • Conformance test (conformance_test.go:144–146) now exercises "jira:" in the accept list and "jira: bad" in the reject list via scopeEntryPattern.MatchString; Go drift back to \S+ would fail the "jira:" case

Fix 2 verified — ValidWorkURI guard:

  • Guard is at main.go:517–519; workURIPattern requires \S+ after the colon, so bare-scheme and space-containing values are refused before routing
  • main_test.go:418–420 pins both the exit code and the error text for jira: bad

New P1 scan: nothing found. Read-only guarantee intact; PhaseVoid || PhaseRetired guard explicit; all four open-prefix characters (/, #, :, -) now covered in scope_test.go; unreadable-lane hedge in text is in place; Phase field carries omitempty.

Known deferred P2s: both accurately described and as-recorded. No new findings at P1 or above.

@claude claude Bot 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.

Reviewed head: e18a0b6f0c25514ca29632086463aabb42a94dd0

Round-2 fold — verification of the two fixes

Fix 1: Schema/Go scope-pattern agreement + conformance coverage

Go side (contracts/org/validate.go:30):

scopeEntryPattern = regexp.MustCompile(`^[a-z][a-z0-9+.-]*:\S*$`)

Uses \S* — bare-scheme entries (jira:) are admitted. ✓

Schema side (contracts/org/schema/org-record-v1.json:59):

"pattern": "^[a-z][a-z0-9+.-]*:\\S*$"

Also \S*. The two representations agree character-for-character. ✓

Conformance test (contracts/org/conformance_test.go:144–146):

{"scope", s.child(t, "terms").child(t, "scope").Items.Pattern,
    []string{"github:acme/api", "jira:PROJ-", "jira:"},
    []string{"PROJ-412", "jira: bad", ""}},

goPattern(t, "scope") returns scopeEntryPattern.MatchString (validate.go:176). The accept list exercises the bare-scheme case; the reject list gates spaces and empty strings. If Go drifts back to \S+, the "jira:" accept case fails. If Go begins accepting "jira: bad", the reject case fails. Indirect but effective guard against Go regression. ✓

The known deferred P2 stands: the schema pattern string is loaded from the JSON but not compiled and executed as a regex — tc.pattern appears only in error messages. A schema revert to \S+ would leave this test green while non-Go consumers disagree. Deferred as recorded; agreed it's a harness-wide change.

Fix 2: Intake's ValidWorkURI guard

cmdIntake (cmd/org/main.go:517–519):

if !org.ValidWorkURI(*work) {
    return fmt.Errorf("-work %q is not a valid work URI (scheme:reference); the kernel could never record it", *work)
}

workURIPattern requires \S+ (one or more non-whitespace after the colon), so bare-scheme values (jira:) and values with embedded spaces (jira: bad) are refused before routing. The test at main_test.go:418–420 pins both the exit code (codeError) and the error text ("not a valid work URI"). Guard is in place and covered. ✓


New P1 scan — none found

Read-only guarantee: cmdIntake calls s.open(args, false), h.RolesForTenant, and h.Load only. h.Append is unreachable from this code path. Exit 0 on all successful report paths; the ValidWorkURI refusal exits via return error (non-zero), which is correct — it is a usage error, not a report. ✓

intakeLane phase guards (main.go:552): the explicit PhaseVoid || PhaseRetired guard added in round-1 is intact. Void/retired lanes are dropped (keep=false) before MatchScope is called, so no zero-value scope-match leaks into the report. ✓

InScope predicate: unchanged from round-1 verification. Cross-scheme exclusion and open-prefix/boundary asymmetry remain correct. ✓

Scope test — # coverage: scope_test.go:25–26 now has:

{"github:owner/repo#", "github:owner/repo#88", true},
{"github:owner/repo#", "github:other/repo#88", false},

All four open-prefix characters (/, #, :, -) are covered. The P2 from round-1 is closed. ✓

Unreadable-lane hedge in text (render/intake.go:45–48): unreadable(in.Lanes) is checked before emitting the no-coverage conclusion; text report hedges correctly when any lane was unreadable. ✓

Phase field with omitempty (render/intake.go:16): unreadable lanes never set lane.Phase, so the field is absent from JSON output rather than zero-valued. P3 from round-1 is closed. ✓


Known deferred P2s — acknowledged, no action expected

  1. Conformance test does not execute the schema regex (contracts/org/conformance_test.go): recorded in the PR comment; fix scoped to a harness-wide change across all four grammar cases on the next slate PR.
  2. JSON covered is binary when unreadable lanes exist (render/intake.go:31): text hedges; JSON does not carry an indeterminate marker. Recorded; additive field queued alongside scope_mismatch work.

Both P2s verified as accurately described. No new findings at P1 or above.

@itsHabib
itsHabib changed the base branch from codex/org-assignment-conflicts to feat/org-sweep August 29, 2026 05:51
@itsHabib
itsHabib changed the base branch from feat/org-sweep to main August 29, 2026 06:02
# Conflicts:
#	cmd/org/AGENTS.md
#	cmd/org/CLAUDE.md
#	cmd/org/main.go
#	cmd/org/main_test.go
@itsHabib

Copy link
Copy Markdown
Owner Author

@claude please review this PR and publish your findings as a FORMAL GitHub review pinned to head 4d54a91 — not only a comment. This head is the fully-reviewed e18a0b6 content plus a mechanical merge of main (the #265/#266 squashes); the conflict resolution took the branch's own files verbatim. Verify the merge introduced nothing new; the two recorded P2 deferrals stand.

@itsHabib

Copy link
Copy Markdown
Owner Author

@codex review

@claude

claude Bot commented Aug 29, 2026

Copy link
Copy Markdown

Claude finished @itsHabib's task in 2m 15s —— View job


PR #269 Review — Merge-head verification (4d54a91)

Reviewed head: 4d54a912bb91fc885771aaa5a19b1d2ba72d8af2

  • Read merge diff (e18a0b6..HEAD) to verify merge introduced nothing new
  • Read full PR diff (origin/main...HEAD) for completeness
  • Confirm two recorded P2 deferrals still stand
  • Post formal GitHub review pinned to 4d54a912bb91fc885771aaa5a19b1d2ba72d8af2

Merge verification

This head is the previously-reviewed e18a0b6 content plus a mechanical merge of origin/main (the #265 sweep squash). The merge commit records four conflict files: cmd/org/AGENTS.md, cmd/org/CLAUDE.md, cmd/org/main.go, cmd/org/main_test.go.

Claim verified: git diff e18a0b6..HEAD on all four contested paths returns empty. The conflict resolution took the branch's own files verbatim. No functional change was introduced to any file owned by this PR. ✓

contracts/ unchanged: git diff e18a0b6..HEAD -- contracts/ also empty. The InScope predicate, scope validation, schema, and tests are byte-identical to the round-2 reviewed state. ✓

Full PR stat vs main matches the PR metadata exactly — 11 files changed, 388 insertions(+), 5 deletions(-). No files added or removed by the merge beyond what was already in the branch. ✓

Guide-pair sync at new head

diff cmd/org/CLAUDE.md cmd/org/AGENTS.md → empty. Byte-identical. The merge did not skew the pair — both took the branch's version of the intake verb entry verbatim. ✓

Round-2 verified findings — all intact

All findings confirmed at e18a0b6 remain in place at the new head:

Finding Status
InScope cross-scheme exclusion (§4.5) via strings.HasPrefix ✓ intact
Drift surfacing (§4.4) — "holds it OUT OF SCOPE" path in intakeLane ✓ intact
ValidWorkURI guard (main.go:517–519) ✓ intact, tested
Schema/Go \S* pattern agreement ✓ intact
# open-prefix coverage in scope_test.go ✓ intact
Read-only guarantee — h.Append unreachable, exit 0 on all report paths ✓ intact
omitempty on Phase in render/intake.go:16 ✓ intact
Explicit PhaseVoid || PhaseRetired guard (main.go:552) ✓ intact

Known deferred P2s — unchanged, accurately recorded

  1. Conformance test does not execute the schema regex (contracts/org/conformance_test.go): tc.pattern is loaded but used only in error messages; only the Go matcher runs. A schema revert to \S+ would leave this test green while non-Go consumers diverge. Deferred to the next slate PR as a harness-wide change across all four grammars.

  2. JSON covered is binary when unreadable lanes exist (render/intake.go:31): text output hedges; -json still emits "covered": false for an unjudged result. Deferred alongside the scope_mismatch work that will consume this field.

Both P2s are accurately described in the recorded deferrals. No new findings at P1 or above. The merge introduced nothing beyond the #265 sweep squash from main, and that squash's changes to the four conflicted files were fully overwritten by the branch's own content.

@claude claude Bot 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.

Reviewed head: 4d54a91

Merge verification

This head is the previously-reviewed e18a0b6 content plus a mechanical merge of origin/main (the #265 sweep squash). The merge commit records four conflict files:

# Conflicts:
#       cmd/org/AGENTS.md
#       cmd/org/CLAUDE.md
#       cmd/org/main.go
#       cmd/org/main_test.go

Claim verified: git diff e18a0b6..HEAD -- cmd/org/AGENTS.md cmd/org/CLAUDE.md cmd/org/main.go cmd/org/main_test.go returns empty. The conflict resolution took the branch's own files verbatim for all four contested paths. No functional change was introduced to any file owned by this PR.

contracts/ unchanged: git diff e18a0b6..HEAD -- contracts/ also returns empty. The InScope predicate, scope validation, schema, and tests are identical to the round-2 reviewed state. ✓

Full PR stat vs main matches the PR metadata exactly:

11 files changed, 388 insertions(+), 5 deletions(-)

No files added or removed by the merge beyond what was already in the branch. ✓

Guide-pair sync at new head

diff cmd/org/CLAUDE.md cmd/org/AGENTS.md → empty. Byte-identical. The merge did not skew the pair — both files took the branch's version of the intake verb entry verbatim. ✓

Round-2 verified findings — still hold

All findings confirmed at e18a0b6 remain in place:

  • InScope cross-scheme exclusion (§4.5): structurally enforced by strings.HasPrefix. ✓
  • Drift surfacing (§4.4): holds it OUT OF SCOPE path intact in intakeLane. ✓
  • ValidWorkURI guard (main.go:517–519): intact, tested. ✓
  • Schema/Go \S* pattern agreement: intact. ✓
  • # open-prefix coverage in scope_test.go: intact. ✓
  • Read-only guarantee: h.Append unreachable from cmdIntake. Exit 0 on all report paths. ✓
  • omitempty on Phase in render/intake.go:16: intact. ✓
  • Explicit PhaseVoid || PhaseRetired guard (main.go:552): intact. ✓

Known deferred P2s — unchanged, accurately recorded

  1. Conformance test does not execute the schema regex (contracts/org/conformance_test.go): tc.pattern is loaded but used only in error messages; only the Go matcher runs against the test cases. A schema revert to \S+ would leave this test green while non-Go consumers diverge. Deferred to the next slate PR as a harness-wide change across all four grammars.

  2. JSON covered is binary when unreadable lanes exist (render/intake.go:31): text output hedges; -json still emits "covered": false for an unjudged result. Deferred alongside the scope_mismatch work that will consume this field.

Both P2s are accurately described in the recorded deferrals. No new findings at P1 or above. The merge introduced nothing beyond the #265 sweep squash from main, and that squash's changes to the four conflicted files were fully overwritten by the branch's own content.

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4d54a912bb

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread contracts/org/validate.go
// charter's scope entry is a prefix, not a work item, and a bare scheme
// (`jira:`) is the widest legal grain a lane can state (see scope.go's
// open-prefix rule). Subject work URIs never get this latitude.
scopeEntryPattern = regexp.MustCompile(`^[a-z][a-z0-9+.-]*:\S*$`)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Version bare-scheme scopes before writing them

When a new client charters -scope jira:, this broadened validator still emits a version-1 chain with min_reader: 1, but any pre-change version-1 reader retains the old \S+ grammar and rejects the genesis record as malformed_work_uri. In a mixed deployment, introducing the advertised scheme-wide scope therefore makes the role inaccessible to older clients despite the record claiming version-1 compatibility; either use a representation accepted by existing v1 readers or advance the record/reader version for this grammar expansion.

Useful? React with 👍 / 👎.

@itsHabib
itsHabib merged commit 7532903 into main Aug 29, 2026
8 checks passed
@itsHabib
itsHabib deleted the feat/org-intake branch August 29, 2026 13:34
itsHabib added a commit that referenced this pull request Aug 30, 2026
…er/annul (#272)

* feat(org): scope drift, deadlines that die with their tenure, recharter/annul

Four slate items and the four P2 deferrals recorded on #269/#270.

- sweep reports scope_drift: work a role holds outside its own charter
  scope, judged by contracts/org.InScope. It is a FINDING, not a refusal —
  Reduce replays every historical record through Admissible, so a scope law
  added today would refuse chains that folded yesterday, and the opt-in
  charter term that would scope it changes every historical digest because
  Terms.Canonical emits every field. FOLLOWUPS records what a real fix costs
  (a canon/v2 scheme), so the next session does not re-derive it.
- next_due dies with the tenure: release, revoke, retire and takeover keep
  only what their own record declares. A released lane was 'late' forever
  against a deadline nobody owned — the supervisor skill carries a written
  workaround for exactly this, which can now go.
- recharter and annul get CLI verbs; both kinds were kernel-admissible with
  no way to write them. recharter prints the terms it REPLACES (it is not a
  patch); annul defaults -target to the tip, the only thing a fold can
  verify.
- Deferrals closed: begin preflights claim blockers before writing anything;
  done discharges a dangling claim by completing it rather than re-claiming
  it (and doneTarget resolves to it); the schema-pattern conformance test now
  compiles and runs the schema's own regex — mutation-checked by reverting
  the scope pattern, which the test catches; intake's JSON carries
  indeterminate + unreadable_lanes so covered:false is not read as proof.
- sweep's attention line is composed from findings that actually fired, so a
  zero count is never rendered.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix: fold round 1 — withdraw recharter, make annul tell the truth

Both P1s were on verbs this PR newly exposed, and both are real.

- recharter is WITHDRAWN, not patched. A holder could recharter itself to a
  higher tier, more effect classes, bigger ceilings, or fewer supervisors,
  all self-signed: checkRecharter verifies only min_reader monotonicity and
  checkWriter accepts the holder's own incarnation. The guard that would fix
  it cannot be written either — Tier is an opaque string, so the kernel has
  no ordering to tell attenuation from escalation. FOLLOWUPS records what
  parent authority would take; until then terms are set once at charter and
  a wrong role is retired and re-chartered, visibly.
- annul no longer claims to withdraw anything. The fold appends the digest to
  Annulled and leaves Terms/Held/Active/NextDue standing, so the verb now
  prints the effect that survives and the verb that would undo it, and the
  guides say repudiation rather than withdrawal. Whether a fold should SKIP
  annulled records is a two-pass question filed in FOLLOWUPS, not smuggled in
  here.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix: fold round 2 — min_reader floor, annul wording in top-level help

Both P2s from the final panel round; the first is a regression this PR
introduced with the -min-reader flag.

- checkCharter refuses a negative min_reader. The schema has declared
  minimum 0 all along and the Go side did not, so -min-reader=-1 wrote a
  record this kernel accepted and every other reader of the contract must
  reject. Replay assessment, the same one this PR's FOLLOWUPS entry demands:
  min_reader had no writer that could set it before this PR (every charter
  hardcoded 1), so the law refuses no existing chain.
- The top-level usage line said annul withdraws the tip. It repudiates it.
  The verb doc, guides and README already said so; the help did not.

Round cap reached: no further panel rounds, residuals to the judge.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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.

1 participant