Skip to content

Extend agent principals: a team of their own, and inheritance up a ladder - #5204

Open
vivekchand wants to merge 15 commits into
mainfrom
principal-scope-ladder
Open

Extend agent principals: a team of their own, and inheritance up a ladder#5204
vivekchand wants to merge 15 commits into
mainfrom
principal-scope-ladder

Conversation

@vivekchand

Copy link
Copy Markdown
Owner

Product record: https://factory.8090.ai/project/b415065f-ab2f-4f53-8864-0c009fd098cb/requirements/d518c6c3-eb50-4b0f-9ed0-59440380b7bf (REQ-OBS-004)

Risk: one new nullable column (agent_meta.team) and a deeper inheritance chain, which means an owner can appear without anyone naming that agent — the confusion the existing rung-reporting was built to prevent. Mitigated by owner_source/team_source naming the rung, guarded by test_each_value_names_its_rung. No session-record change, no ingest change, no re-stamp. Undone by dropping the column.

The call

I built a second ownership model in #5165. Principals are better and it isn't close — so that PR is closed and this keeps only the gap.

Identity there is derived, not stamped: a hash of (node_id, runtime, agent_id), all of which sessions already carries. No migration, retroactive by construction, cannot go stale. My version persisted owner/team onto session rows at ingest — buying a cheap WHERE and paying with a migration, a full-table re-stamp inside the write lock on an ordinary label edit, and stored values that drift from the labels producing them. Against a columnar store, that's a bad trade. Deriving won, and the stamping version was mine.

What principals genuinely didn't cover

Inheritance was one rung deep. An agent inherited only its runtime's owner, so "everything on this build box belongs to Platform" was unsayable and a fleet had to be labelled agent by agent — the labelling that never gets done, which is why ownership renders empty.

Team shared the owner's free-text field. agent_meta was (agent_key, owner, notes), and the route said "claim it for a person or team". One field, two questions.

What this adds

team as its own column, and the fallback becomes a ladder — agent → machine → runtime — with owner and team resolving independently:

claude_code  main      box1  owner='Ada'   (runtime)  team='Platform'  (node)
claude_code  research  box1  owner='Grace' (agent)    team='Research'  (agent)
codex        main      box2  owner=''      ()         team=''          ()

A machine can belong to a team while a person owns one agent on it. Bind both to one rung and that pair is unexpressible.

New: POST /api/govern/scopes/<node|runtime>/<value>/owner, which validates the scope was actually observed — same reason the principal write checks its id.

The requirement changed before the code did

Written the new way (FLYWHEEL §0c): REQ-OBS-004 first. Implementation then found it wrong — a principal routinely spans workspaces, so a workspace rung has nothing unambiguous to inherit from, and adding workspace to identity would split one agent into several. AC-OBS-004.2 was amended to machine-then-runtime, with the reason, before any code. That's the order working.

REQ-OBS-RSO-004 and the two blueprint sections describing the stamped model are marked withdrawn/superseded, so nobody builds from a spec we rejected.

Tests

11 new. The load-bearing one is test_ownership_is_not_stored_on_sessions, which asserts the columns from #5165 never come back, and test_a_label_applies_to_history_already_collected, which pins the property stamping gives up. Ratchet 43/108 → 49/114.

@8090-software-factory

Copy link
Copy Markdown

✅ Drift Bot (ClawMetry): no drift detected

Drift Bot analyzed the changed files against this project's blueprints and requirements and found no drift.

@github-actions

github-actions Bot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Visual diff

Comparing e2cb66b6c3e0 (head) against the PR base branch.

44 of 70 comparison(s) flagged (>1% pixel diff).

View Before After Diff
desktop overview before after diff · 0.02%
desktop flow before after diff · 0.05%
desktop brain ⚠️ before after diff · 100.00%
desktop usage before after diff · 0.00%
desktop crons ⚠️ before after diff · 100.00%
desktop memory before after diff · 0.04%
desktop security ⚠️ before after diff · 100.00%
desktop subagents before after diff · 0.02%
desktop transcripts ⚠️ before after diff · 100.00%
desktop logs before after diff · 0.00%
desktop skills before after diff · 0.01%
desktop models ⚠️ before after diff · 100.00%
desktop approvals ⚠️ before after diff · 2.65%
desktop alerts ⚠️ before after diff · 100.00%
desktop notifications ⚠️ before after diff · 100.00%
desktop limits ⚠️ before after diff · 100.00%
desktop history ⚠️ before after diff · 100.00%
desktop channels before after diff · 0.34%
desktop harness ⚠️ before after diff · 100.00%
desktop inventory before after diff · 0.01%
desktop nemoclaw before after diff · 0.20%
desktop guard before after diff · 0.26%
desktop signals before after diff · 0.00%
desktop policy before after diff · 0.02%
desktop selfevolve ⚠️ before after diff · 100.00%
desktop swimlane before after diff · 0.00%
desktop tool-catalog ⚠️ before after diff · 100.00%
desktop tracing ⚠️ before after diff · 100.00%
desktop turn-anatomy ⚠️ before after diff · 100.00%
desktop version-impact ⚠️ before after diff · 100.00%
desktop context-economics ⚠️ before after diff · 100.00%
desktop agents before after diff · 0.02%
desktop evals ⚠️ before after diff · 100.00%
desktop bench ⚠️ before after diff · 100.00%
desktop trail ⚠️ before after diff · 100.00%
mobile overview ⚠️ before after diff · 100.00%
mobile flow before after diff · 0.32%
mobile brain ⚠️ before after diff · 100.00%
mobile usage before after diff · 0.01%
mobile crons before after diff · 0.02%
mobile memory ⚠️ before after diff · 100.00%
mobile security ⚠️ before after diff · 100.00%
mobile subagents ⚠️ before after diff · 100.00%
mobile transcripts ⚠️ before after diff · 100.00%
mobile logs ⚠️ before after diff · 5.83%
mobile skills before after diff · 0.01%
mobile models ⚠️ before after diff · 100.00%
mobile approvals ⚠️ before after diff · 100.00%
mobile alerts before after diff · 0.00%
mobile notifications before after diff · 0.01%
mobile limits before after diff · 0.00%
mobile history before after diff · 0.01%
mobile channels before after diff · 0.01%
mobile harness ⚠️ before after diff · 100.00%
mobile inventory ⚠️ before after diff · 100.00%
mobile nemoclaw ⚠️ before after diff · 100.00%
mobile guard ⚠️ before after diff · 100.00%
mobile signals ⚠️ before after diff · 100.00%
mobile policy ⚠️ before after diff · 100.00%
mobile selfevolve ⚠️ before after diff · 100.00%
mobile swimlane ⚠️ before after diff · 3.77%
mobile tool-catalog ⚠️ before after diff · 100.00%
mobile tracing ⚠️ before after diff · 100.00%
mobile turn-anatomy ⚠️ before after diff · 100.00%
mobile version-impact ⚠️ before after diff · 100.00%
mobile context-economics before after diff · 0.01%
mobile agents ⚠️ before after diff · 100.00%
mobile evals ⚠️ before after diff · 6.00%
mobile bench ⚠️ before after diff · 100.00%
mobile trail before after diff · 0.01%

Folder: e2cb66b6c3e0. Full PNGs also attached as a workflow artefact.

Generated by visual-diff bot. Pixel diffs >1% flagged; eyeball the table before merging. This check is non-blocking — fail = bot bug, not a code problem.

@8090-software-factory

Copy link
Copy Markdown

✅ Drift Bot (ClawMetry): no drift detected

Drift Bot analyzed the changed files against this project's blueprints and requirements and found no drift.

github-actions Bot pushed a commit that referenced this pull request Aug 25, 2026
@8090-software-factory

Copy link
Copy Markdown

✅ Drift Bot (ClawMetry): no drift detected

Drift Bot analyzed the changed files against this project's blueprints and requirements and found no drift.

github-actions Bot pushed a commit that referenced this pull request Aug 25, 2026
@vivekchand
vivekchand force-pushed the principal-scope-ladder branch from 831359b to 8f934ce Compare August 25, 2026 21:21
@8090-software-factory

Copy link
Copy Markdown

✅ Drift Bot (ClawMetry): no drift detected

Drift Bot analyzed the changed files against this project's blueprints and requirements and found no drift.

@vivekchand
vivekchand force-pushed the principal-scope-ladder branch from 8f934ce to 896fbfc Compare August 25, 2026 21:23
@8090-software-factory

Copy link
Copy Markdown

⚠️ Drift Bot (ClawMetry): 1 potential drift finding(s)

1. Blueprint: Governance Policy and Approval

File: routes/govern.py

The blueprint specifies that ownership resolves at agent level first and falls back to the agent's runtime (2-level hierarchy), but the code now implements a 3-level hierarchy (agent → node → runtime). The requirement was amended before implementation to include machine-level labels, but the blueprint has not been updated to reflect this change.
343

@vivekchand vivekchand left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Test plan — principal scope ladder (3-level ownership)

Fast checks first:

make lint
python3 -m pytest tests/test_principal_scope_ladder.py -v
make test

The new test file covers all six AC-OBS-004 criteria (12 tests). All should pass before merge.

Manual smoke test — new /api/govern/scopes/ endpoint:

# Write owner at node scope
curl -X POST http://localhost:8900/api/govern/scopes/node/<node_id>/owner \
  -H 'Content-Type: application/json' \
  -d '{"owner": "alice", "team": "infra"}'

# Verify inheritance: an agent on that node with no explicit owner should inherit alice/infra
curl http://localhost:8900/api/govern/principals | jq '.[] | select(.principal_id == "<pid>") | {owner, owner_source, team, team_source}'
# Expect: owner_source = "node", team_source = "node"

# Write a more-specific agent-level owner; node-level should be shadowed
curl -X POST http://localhost:8900/api/govern/principals/<pid>/owner \
  -H 'Content-Type: application/json' \
  -d '{"owner": "bob", "team": "ml"}'
curl http://localhost:8900/api/govern/principals | jq '.[] | select(.principal_id == "<pid>") | {owner, owner_source, team, team_source}'
# Expect: owner_source = "agent", team_source = "agent"

Edge cases to verify:

  • Agent has owner set but no teamteam should fall through to node-level, then runtime-level (independent resolution)
  • Node scope key format: must be "node:<node_id>" (matches _NODE_SCOPE_PREFIX constant)
  • Unobserved scope ID in POST /api/govern/scopes/node/<id>/owner → should 404 (scope must exist in agent_meta or be observed)

Drift-bot finding — real contradiction, blueprint update required before merge:

The Governance Policy blueprint currently documents a 2-level hierarchy (agent → runtime). This PR implements a 3-level hierarchy (agent → node → runtime). Drift bot correctly flags this as a contradiction, not just undocumented code — so the E2E Gate will stay red until the blueprint is updated.

Action needed: update the "Governance Policy and Approval" blueprint at factory.8090.ai to document the node-scope level, then re-sync (make ac-sync or equivalent) so the E2E Gate can go green.

The implementation itself looks correct — owner and team resolve independently through the ladder, notes takes the first non-empty value, and the schema migration for the team column follows the established _SCHEMA_MIGRATIONS pattern.


Generated by Claude Code

github-actions Bot pushed a commit that referenced this pull request Aug 25, 2026
@vivekchand
vivekchand force-pushed the principal-scope-ladder branch from 896fbfc to 7604a83 Compare August 26, 2026 00:20
@8090-software-factory

Copy link
Copy Markdown

⚠️ Drift Bot (ClawMetry): 3 potential drift finding(s)

1. Blueprint: Governance Policy and Approval

File: routes/govern.py:343

The blueprint specifies that ownership resolves at agent level first and falls back to the agent's runtime (2-level hierarchy), but the code implements a 3-level hierarchy (agent → node → runtime) as amended in REQ-OBS-004.2 before implementation. The blueprint must be updated to reflect the machine-level scope in the inheritance chain.

2. Blueprint: Governance Policy and Approval

File: routes/govern.py:172

The blueprint does not document the new POST /api/govern/scopes/<node|runtime>/<value>/owner endpoint that allows setting ownership at the machine or runtime level, which enables the multi-level inheritance hierarchy described in REQ-OBS-004.2.

3. Blueprint: Governance Policy and Approval

File: routes/govern.py:343

The blueprint does not mention that team is a separate attribute from owner, nor that they resolve independently up the inheritance ladder. The code implements this as a key feature per REQ-OBS-004.1 and REQ-OBS-004.4, distinguishing "who owns this agent" from "which team pays for it."

Comment thread routes/govern.py

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Drift Bot (ClawMetry) — Blueprint: Governance Policy and Approval

The blueprint specifies that ownership resolves at agent level first and falls back to the agent's runtime (2-level hierarchy), but the code implements a 3-level hierarchy (agent → node → runtime) as amended in REQ-OBS-004.2 before implementation. The blueprint must be updated to reflect the machine-level scope in the inheritance chain.

Comment thread routes/govern.py
_store_call("set_agent_meta", agent_key=pid, owner=owner, notes=notes)
_store_call("set_agent_meta", agent_key=pid, owner=owner,
notes=notes, team=team)
except Exception:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Drift Bot (ClawMetry) — Blueprint: Governance Policy and Approval

The blueprint does not document the new POST /api/govern/scopes/<node|runtime>/<value>/owner endpoint that allows setting ownership at the machine or runtime level, which enables the multi-level inheritance hierarchy described in REQ-OBS-004.2.

Copy link
Copy Markdown
Owner Author

blocked on author decision — skipping (auto-mergeability sweep)

Drift Bot found 3 drift finding(s) on the head commit. The blueprint contradictions need to be addressed by the author before this PR can be merged.


Generated by Claude Code

github-actions Bot pushed a commit that referenced this pull request Aug 26, 2026
vivekchand pushed a commit that referenced this pull request Aug 26, 2026
Bring branch up to date with main.

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

Copy link
Copy Markdown
Owner Author

✨ auto-fixed: merged main into branch to bring it up to date (was BEHIND by multiple commits)


Generated by Claude Code

@8090-software-factory

Copy link
Copy Markdown

⚠️ Drift Bot (ClawMetry): 3 potential drift finding(s)

1. Blueprint: Governance Policy and Approval

File: routes/govern.py:172

The blueprint does not document the new POST /api/govern/scopes/<node|runtime>//owner endpoint that allows setting ownership and team attributes at the machine or runtime level, enabling the multi-level inheritance hierarchy.

2. Blueprint: Governance Policy and Approval

File: routes/govern.py:343

The blueprint specifies a 2-level ownership hierarchy (agent → runtime), but the code implements a 3-level hierarchy (agent → node → runtime) as amended in REQ-OBS-004.2. The blueprint must document the machine-level scope and the independent resolution of owner and team attributes.

3. Blueprint: Governance Policy and Approval

File: clawmetry/local_store.py:3834

The blueprint does not document that team is a separate attribute from owner with independent inheritance up the scope ladder. The code implements them as distinct fields resolving independently per AC-OBS-004.1 and AC-OBS-004.4.

Comment thread routes/govern.py
_store_call("set_agent_meta", agent_key=pid, owner=owner, notes=notes)
_store_call("set_agent_meta", agent_key=pid, owner=owner,
notes=notes, team=team)
except Exception:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Drift Bot (ClawMetry) — Blueprint: Governance Policy and Approval

The blueprint does not document the new POST /api/govern/scopes/<node|runtime>//owner endpoint that allows setting ownership and team attributes at the machine or runtime level, enabling the multi-level inheritance hierarchy.

Comment thread routes/govern.py

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Drift Bot (ClawMetry) — Blueprint: Governance Policy and Approval

The blueprint specifies a 2-level ownership hierarchy (agent → runtime), but the code implements a 3-level hierarchy (agent → node → runtime) as amended in REQ-OBS-004.2. The blueprint must document the machine-level scope and the independent resolution of owner and team attributes.

Comment thread clawmetry/local_store.py
@@ -3803,13 +3834,18 @@ def query_agent_principals(
Each row::

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Drift Bot (ClawMetry) — Blueprint: Governance Policy and Approval

The blueprint does not document that team is a separate attribute from owner with independent inheritance up the scope ladder. The code implements them as distinct fields resolving independently per AC-OBS-004.1 and AC-OBS-004.4.

github-actions Bot pushed a commit that referenced this pull request Aug 26, 2026
@8090-software-factory

Copy link
Copy Markdown

⚠️ Drift Bot (ClawMetry): 3 potential drift finding(s)

1. Blueprint: Governance Policy and Approval

File: routes/govern.py:172

The blueprint does not document the new POST /api/govern/scopes/<node|runtime>//owner endpoint that allows setting ownership and team attributes at the machine or runtime level, enabling the multi-level inheritance hierarchy described in REQ-OBS-004.

2. Blueprint: Governance Policy and Approval

File: routes/govern.py:343

The blueprint specifies a 2-level ownership hierarchy (agent → runtime), but the code implements a 3-level hierarchy (agent → machine → runtime) as amended in REQ-OBS-004.2. The blueprint must be updated to document machine-level scopes and the independent resolution of owner and team attributes.

3. Blueprint: Governance Policy and Approval

File: clawmetry/local_store.py:3943

The blueprint does not document that team is a separate attribute from owner with independent inheritance up the scope ladder. The code implements both attributes as distinct fields resolving independently per AC-OBS-004.1 and AC-OBS-004.4.

Comment thread routes/govern.py
_store_call("set_agent_meta", agent_key=pid, owner=owner, notes=notes)
_store_call("set_agent_meta", agent_key=pid, owner=owner,
notes=notes, team=team)
except Exception:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Drift Bot (ClawMetry) — Blueprint: Governance Policy and Approval

The blueprint does not document the new POST /api/govern/scopes/<node|runtime>//owner endpoint that allows setting ownership and team attributes at the machine or runtime level, enabling the multi-level inheritance hierarchy described in REQ-OBS-004.

Comment thread routes/govern.py

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Drift Bot (ClawMetry) — Blueprint: Governance Policy and Approval

The blueprint specifies a 2-level ownership hierarchy (agent → runtime), but the code implements a 3-level hierarchy (agent → machine → runtime) as amended in REQ-OBS-004.2. The blueprint must be updated to document machine-level scopes and the independent resolution of owner and team attributes.

Comment thread clawmetry/local_store.py

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Drift Bot (ClawMetry) — Blueprint: Governance Policy and Approval

The blueprint does not document that team is a separate attribute from owner with independent inheritance up the scope ladder. The code implements both attributes as distinct fields resolving independently per AC-OBS-004.1 and AC-OBS-004.4.

Comment thread clawmetry/local_store.py
@@ -6117,13 +6070,18 @@ def query_agent_principals(
Each row::

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Drift Bot (ClawMetry) — Blueprint: Governance Policy and Approval

The query_agent_principals() method implements a 3-level inheritance ladder (agent → node → runtime) per AC-OBS-004.2, but the blueprint's AgentPrincipalRegistry Key Contracts only document a 2-level hierarchy (agent → runtime), omitting the node/machine scope as an intermediate rung.

"""Return the agent_meta key for a machine-wide label on node_id."""
return AgentMetaMixin._NODE_SCOPE_PREFIX + str(node_id or "").strip()

def set_agent_meta(

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Drift Bot (ClawMetry) — Blueprint: Governance Policy and Approval

The set_agent_meta() method now accepts team as a distinct, independently updateable parameter per AC-OBS-004.1, but the blueprint's AgentPrincipalRegistry Key Contracts section does not document team as a separate parameter from owner and notes.

Comment thread routes/govern.py
return jsonify({"ok": False, "error": "write failed"}), 200
return jsonify({"ok": True, "principalId": pid, "owner": owner})
return jsonify({"ok": True, "principalId": pid, "owner": owner, "team": team})

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Drift Bot (ClawMetry) — Blueprint: Governance Policy and Approval

A new endpoint POST /api/govern/scopes/<node|runtime>//owner is implemented to assign ownership and team at machine or runtime scope per AC-OBS-004.2, enabling inheritance across multiple agents, but this endpoint and its Key Contracts are not documented in the blueprint's AgentPrincipalRegistry section.

Copy link
Copy Markdown
Owner Author

✨ auto-fixed: merged main into branch to resolve stale base and trigger fresh CI


Generated by Claude Code

Copy link
Copy Markdown
Owner Author

Maintainer bot status (2026-09-13): drift-bot is posting a failure status on this commit, which causes the E2E Gate to fail.

Action needed: Visit https://factory.8090.ai, find the Blueprint/requirement for the agent principals / team ownership feature, and approve the drift or update the product record. Once drift-bot posts success, the E2E Gate will re-evaluate.


Generated by Claude Code

Copy link
Copy Markdown
Owner Author

Auto-janitor (mergeability sweep): E2E Gate (required) is failing on this PR because the drift-bot commit status is failure. Drift Bot checks blueprint compliance — this is a real semantic failure, not a transient flake, so a rerun won't clear it. The PR needs a human to review the Drift Bot finding and either address the blueprint concern or get it waived.

All other CI legs (Syntax & Lint, API Tests, MOAT, pip install matrix, E2E Browser, Store invariants, Entitlement API, etc.) are green on the current head.


Generated by Claude Code

Copy link
Copy Markdown
Owner Author

Autonomous maintainer audit (2026-09-13)

All major CI jobs are green on this PR. The single blocker is:

Drift Bot: failed — 'drift-bot': failure

The E2E Gate exits immediately because Drift Bot has already posted a failure. Despite this PR citing a proper 8090 factory product record (REQ-OBS-004), the Drift Bot is reporting failure.

Possible causes:

  • The blueprint acceptance criteria diverged from the implementation (blueprint was amended mid-flight per the PR body — AC-OBS-004.2 changed from workspace-then-runtime to machine-then-runtime)
  • The Drift Bot snapshot predates the blueprint amendment and is still checking the original spec

What's needed: Re-sync the Drift Bot against the amended blueprint. The PR body explicitly documents the requirement change with the correct reasoning; the implementation appears to match the amended spec. This likely just needs the factory's Drift Bot to re-read the updated blueprint.


Generated by Claude Code

Copy link
Copy Markdown
Owner Author

blocked on author decision — skipping (auto-mergeability sweep)

E2E Gate fails due to Drift Bot — the code contradicts a Blueprint in the 8090 Software Factory. This requires the author to reconcile the implementation with the product record.


Generated by Claude Code

Copy link
Copy Markdown
Owner Author

Auto-rebase attempted; aborted due to 80+ add/add conflicts between this branch and main. Both sides added the same files (i18n docs, new test files, ci.yml, CHANGELOG.md, app.js, MODULE_MAP.md, etc.) across 80+ paths — well beyond the 5-file mechanical-resolution limit. This needs a manual rebase or the GitHub "Update branch" (merge) button to bring it up to date with main.


Generated by Claude Code

Copy link
Copy Markdown
Owner Author

blocked on author decision — skipping (auto-mergeability sweep)

E2E Gate (required) is failing because the Drift Bot leg reports a blueprint contradiction ('drift-bot': failure). Addressing the Drift Bot finding requires reviewing the blueprint this PR is alleged to contradict — not a mechanical fix this sweep can make.


Generated by Claude Code

Copy link
Copy Markdown
Owner Author

Automated sweep — mergeability blocker identified

E2E Gate fails on this PR due to Drift Bot ('drift-bot': failure).

Root cause: The Governance Policy blueprint at factory.8090.ai documents a 2-level hierarchy (agent → runtime), but this PR implements a 3-level hierarchy (agent → node → runtime). Drift Bot flags the implementation as contradicting the documented architecture.

What's needed to unblock:

  1. Update the Governance Policy blueprint at factory.8090.ai to document the 3-level hierarchy this PR introduces.
  2. Re-sync locally (make ac-sync) so the updated blueprint is pulled in.
  3. Re-push or re-run CI to re-trigger Drift Bot — it should pass once the blueprint matches the implementation.

Additionally, this branch is behind main — a rebase or branch update will be needed before merge.

No code changes were made by this automated sweep.


Generated by Claude Code

Copy link
Copy Markdown
Owner Author

Automated maintainer check — action needed

The E2E Gate is blocked by a Drift Bot failure. Drift Bot is a required leg that verifies the diff matches the product Blueprint from 8090 Software Factory. It fails immediately at [0s]:

[0s] Drift Bot: failed: 1 of 1 matching check(s) failed
    'drift-bot': failure

This is not a transient failure — Drift Bot catches "this diff contradicts a Blueprint" and cannot be resolved by re-running CI.

Needed from a human: Review the Blueprint for this feature in 8090 Software Factory and reconcile the implementation. Either update the code to match the Blueprint, or update the Blueprint to reflect the intended design, and re-run CI.

This PR cannot be merged until Drift Bot passes.


Generated by Claude Code

Copy link
Copy Markdown
Owner Author

Blocked by Drift Bot failure. The E2E Gate log shows Drift Bot: 1 of 1 matching check(s) failed. This PR modifies route files and the agent_meta schema, so docs/MODULE_MAP.md likely needs regeneration. Fix: run python3 scripts/gen_module_map.py and commit the updated file; also check scripts/check_ac_coverage.py --check to confirm the AC ratchet is still holding.


Generated by Claude Code

Copy link
Copy Markdown
Owner Author

blocked on author decision — skipping (auto-mergeability sweep): E2E Gate fails on drift-bot (external 8090 Factory product-record check). Needs the factory blueprint to mark this implementation as satisfying the requirement, or a No-PRD: exception if applicable.


Generated by Claude Code

Copy link
Copy Markdown
Owner Author

Automated maintainer run blocked: E2E Gate failing because the Drift Bot check (drift-bot) reported a failure on this PR's head commit (2785812745bf). This means the 8090 Software Factory found something in the diff that contradicts a Blueprint. Needs a human to review the Drift Bot findings and either address the contradiction or mark it accepted in the Factory before this PR can merge.

All other CI legs (39 checks) are green.


Generated by Claude Code

Copy link
Copy Markdown
Owner Author

blocked on author decision — skipping (auto-mergeability sweep)

Blocker: drift-bot commit status fails with 5 drift findings. The findings are Blueprint documentation gaps that require updating the Factory record at factory.8090.ai — not a code change this sweep can make.


Generated by Claude Code

Copy link
Copy Markdown
Owner Author

Autonomous maintainer sweep (2026-09-13)

Status: Blocked by Drift Bot — 7 blueprint drift findings, all in the same blueprint.

All CI checks pass (API tests, MOAT, store invariants, E2E, install matrix, etc.). The only blocker is the drift-bot: failure commit status, which is a required gate inside E2E Gate (required).

Root cause: The "Governance Policy and Approval" blueprint was not updated when the code added:

  1. A separate team column (independent of owner) with its own inheritance
  2. A 3-level hierarchy (agent → node → runtime) instead of the blueprint's 2-level (agent → runtime)
  3. owner_source and team_source fields in the response
  4. A new POST /api/govern/scopes/<node|runtime>/<value>/owner endpoint

All 7 Drift Bot findings point to the same blueprint: https://factory.8090.ai/project/b415065f-ab2f-4f53-8864-0c009fd098cb/blueprints/b1dc4360-9a11-4e4b-9488-9b5ddead1cdc

Human action needed: Update the blueprint at the link above to document:

  • The team attribute as a distinct field from owner
  • The 3-rung inheritance ladder (agent → node → runtime, for both owner and team independently)
  • owner_source / team_source fields in the principal response
  • The new POST /api/govern/scopes/<scope>/<value>/owner endpoint
  • The node-level scope as an intermediate rung in the ladder

The PR body already has the narrative (see "What this adds" section). The blueprint update should mirror it. Once the blueprint is updated and Drift Bot re-checks, the E2E Gate will pass.

This cannot be auto-resolved from the sandbox — it requires access to the 8090 Software Factory product portal.


Generated by Claude Code

@8090-software-factory

Copy link
Copy Markdown

⚠️ Drift Bot (ClawMetry): 5 potential drift finding(s)

1. Blueprint: Governance Policy and Approval

File: clawmetry/local_store.py:6070

The query_agent_principals() method implements a 3-level inheritance ladder (agent → node → runtime) where owner and team resolve independently, but the blueprint only documents 2-level inheritance (agent → runtime), omitting the node/machine scope as an intermediate rung.

2. Blueprint: Governance Policy and Approval

File: clawmetry/local_store_agent_meta.py:32

The set_agent_meta() method now accepts team as a distinct, independently updateable parameter separate from owner and notes, but the blueprint's AgentPrincipalRegistry Key Contracts section does not document team as a separate parameter.

3. Blueprint: Governance Policy and Approval

File: routes/govern.py:175

A new endpoint POST /api/govern/scopes/<node|runtime>//owner is implemented to assign ownership and team at machine or runtime scope, enabling inheritance across multiple agents, but this endpoint and its behavior are not documented in the blueprint's AgentPrincipalRegistry Key Contracts section.

4. Blueprint: Governance Policy and Approval

File: routes/govern.py:156

The POST /api/govern/principals/<principal_id>/owner endpoint now accepts and returns team as a distinct field and returns team_source naming the inheritance rung, but the blueprint's Key Contracts only document owner and notes parameters/responses, not team or team_source fields.

5. Blueprint: Governance Policy and Approval

File: clawmetry/local_store.py:6179

The query_agent_principals() method returns team and team_source fields allowing owner and team to resolve independently up the inheritance ladder, but the blueprint's AgentPrincipalRegistry documentation does not describe these as response fields or explain the independent resolution model.

Comment thread clawmetry/local_store.py
@@ -6117,13 +6070,18 @@ def query_agent_principals(
Each row::

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Drift Bot (ClawMetry) — Blueprint: Governance Policy and Approval

The query_agent_principals() method implements a 3-level inheritance ladder (agent → node → runtime) where owner and team resolve independently, but the blueprint only documents 2-level inheritance (agent → runtime), omitting the node/machine scope as an intermediate rung.

"""Return the agent_meta key for a machine-wide label on node_id."""
return AgentMetaMixin._NODE_SCOPE_PREFIX + str(node_id or "").strip()

def set_agent_meta(

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Drift Bot (ClawMetry) — Blueprint: Governance Policy and Approval

The set_agent_meta() method now accepts team as a distinct, independently updateable parameter separate from owner and notes, but the blueprint's AgentPrincipalRegistry Key Contracts section does not document team as a separate parameter.

Comment thread routes/govern.py
return jsonify({"ok": False, "error": "write failed"}), 200
return jsonify({"ok": True, "principalId": pid, "owner": owner})
return jsonify({"ok": True, "principalId": pid, "owner": owner, "team": team})

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Drift Bot (ClawMetry) — Blueprint: Governance Policy and Approval

A new endpoint POST /api/govern/scopes/<node|runtime>//owner is implemented to assign ownership and team at machine or runtime scope, enabling inheritance across multiple agents, but this endpoint and its behavior are not documented in the blueprint's AgentPrincipalRegistry Key Contracts section.

@8090-software-factory

Copy link
Copy Markdown

⚠️ Drift Bot (ClawMetry): 5 potential drift finding(s)

1. Blueprint: Governance Policy and Approval

File: clawmetry/local_store.py:6070

The query_agent_principals() method implements a 3-level inheritance ladder (agent → node → runtime) where owner and team resolve independently per AC-OBS-004.2, but the blueprint's AgentPrincipalRegistry documentation only describes 2-level inheritance (agent → runtime), omitting the node/machine scope as an intermediate rung.

2. Blueprint: Governance Policy and Approval

File: clawmetry/local_store_agent_meta.py:32

The set_agent_meta() method accepts team as a distinct, independently updateable parameter per AC-OBS-004.1, but the blueprint's AgentPrincipalRegistry Key Contracts section does not document team as a separate parameter.

3. Blueprint: Governance Policy and Approval

File: routes/govern.py:175

A new endpoint POST /api/govern/scopes/<node|runtime>//owner is implemented to assign ownership and team at machine or runtime scope per AC-OBS-004.2, enabling inheritance across multiple agents, but this endpoint is not documented in the blueprint's AgentPrincipalRegistry Key Contracts section.

4. Blueprint: Governance Policy and Approval

File: routes/govern.py:156

The POST /api/govern/principals/<principal_id>/owner endpoint now accepts and returns team as a distinct field and returns team_source naming the inheritance rung per AC-OBS-004.3, but the blueprint's Key Contracts only document owner and notes parameters/responses.

5. Blueprint: Governance Policy and Approval

File: clawmetry/local_store.py:6179

The query_agent_principals() method returns team and team_source fields allowing owner and team to resolve independently up the inheritance ladder per AC-OBS-004.4, but the blueprint's AgentPrincipalRegistry documentation does not describe these as response fields or explain the independent resolution model.

Comment thread clawmetry/local_store.py
@@ -6117,13 +6070,18 @@ def query_agent_principals(
Each row::

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Drift Bot (ClawMetry) — Blueprint: Governance Policy and Approval

The query_agent_principals() method implements a 3-level inheritance ladder (agent → node → runtime) where owner and team resolve independently per AC-OBS-004.2, but the blueprint's AgentPrincipalRegistry documentation only describes 2-level inheritance (agent → runtime), omitting the node/machine scope as an intermediate rung.

"""Return the agent_meta key for a machine-wide label on node_id."""
return AgentMetaMixin._NODE_SCOPE_PREFIX + str(node_id or "").strip()

def set_agent_meta(

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Drift Bot (ClawMetry) — Blueprint: Governance Policy and Approval

The set_agent_meta() method accepts team as a distinct, independently updateable parameter per AC-OBS-004.1, but the blueprint's AgentPrincipalRegistry Key Contracts section does not document team as a separate parameter.

Comment thread routes/govern.py
return jsonify({"ok": False, "error": "write failed"}), 200
return jsonify({"ok": True, "principalId": pid, "owner": owner})
return jsonify({"ok": True, "principalId": pid, "owner": owner, "team": team})

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Drift Bot (ClawMetry) — Blueprint: Governance Policy and Approval

A new endpoint POST /api/govern/scopes/<node|runtime>//owner is implemented to assign ownership and team at machine or runtime scope per AC-OBS-004.2, enabling inheritance across multiple agents, but this endpoint is not documented in the blueprint's AgentPrincipalRegistry Key Contracts section.

Copy link
Copy Markdown
Owner Author

PR health check · 2026-09-13

Blocked — 7 Drift Bot findings on the [Governance Policy and Approval] Blueprint

The E2E Gate is failing at second 0 because the code expands the scope of the Blueprint without a corresponding Blueprint update. No amount of local fixes resolves this — the Blueprint at factory.8090.ai needs to be updated first. The 7 gaps Drift Bot identified:

  1. 3-level inheritance hierarchy (agent → node → runtime) — Blueprint currently describes only a flat owner model; the ladder in clawmetry/local_store.py is undocumented
  2. team field on agent_principals — new column, not in Blueprint schema
  3. owner_source field — Blueprint doesn't mention provenance tracking
  4. team_source field — same
  5. POST /api/govern/scopes/<node|runtime>/<value>/owner endpoint — entirely new write surface, not described anywhere in Blueprint
  6. 3-level scope resolution order — which level wins when all three are set is a non-obvious invariant that the Blueprint should call out
  7. Principal set_agent_meta / query_agent_principals signatures — the new parameters on these store functions aren't reflected in any documented API contract

Next step: Update the [Governance Policy and Approval] Blueprint at factory.8090.ai to document items 1–7 above, then re-run CI. Drift Bot re-checks on every push to the PR branch.

Smoke test plan (for when Blueprint is updated and CI is green):

make test

# Read principals for a runtime
curl -sS "http://localhost:8900/api/govern/principals?runtime=claude_code"

# Set node-level owner with team
curl -sS -X POST http://localhost:8900/api/govern/scopes/node/my-box/owner \
  -H 'Content-Type: application/json' \
  -d '{"owner":"Ada","team":"Platform"}'

# Verify inheritance: agent-level owner should take precedence over node
# (set agent owner and confirm it wins in the resolved principal response)

No code changes are needed on this PR unless the Blueprint update reveals an inconsistency. The implementation looks correct against the intent; it just outran the documented spec.


Generated by Claude Code

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