From 0e8ca002fc1dd76ae84c71f8d24dfd1ac7096ff5 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 1 Jul 2026 07:01:19 +0100 Subject: [PATCH 001/242] feat(skill-cleaner): add exclusive root scans (#19) --- CHANGELOG.md | 3 ++ skills/skill-cleaner/SKILL.md | 2 + .../scripts/skill-cleaner.test.ts | 23 +++++++++++ skills/skill-cleaner/scripts/skill-cleaner.ts | 39 +++++++++++++------ 4 files changed, 56 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 716b17b..1584b59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ summary: Timeline of guardrail helper changes mirrored from Sweetistics and rela # Changelog +## 2026-07-01 — Isolated Skill Audits +- Added `skill-cleaner --root-only` for auditing only explicitly supplied skill roots without Codex inventory noise. Thanks @its-How. + ## 2026-07-01 — OSS Maintainer Orchestration - Expanded `maintainer-orchestrator` into a long-running control plane with one worker thread per repository, a 10-thread concurrency target with immediate smallest-queue refill, concrete status-based thread titles, safe repository synchronization, forgotten-work preservation, PR rewrite/deduplication, decision-ready risk and diff summaries, durable `VISION.md` policy capture, dependency audits, release proposals with strongest-first highlights, and a persistent daily log plus heartbeat. diff --git a/skills/skill-cleaner/SKILL.md b/skills/skill-cleaner/SKILL.md index 678766f..0bed02d 100644 --- a/skills/skill-cleaner/SKILL.md +++ b/skills/skill-cleaner/SKILL.md @@ -23,6 +23,7 @@ node --experimental-strip-types skills/skill-cleaner/scripts/skill-cleaner.ts -- node --experimental-strip-types skills/skill-cleaner/scripts/skill-cleaner.ts --months 6 --max-log-mb 800 --deep-logs node --experimental-strip-types skills/skill-cleaner/scripts/skill-cleaner.ts --context-tokens 272000 --budget-percent 2 --no-logs node --experimental-strip-types skills/skill-cleaner/scripts/skill-cleaner.ts --root ~/Dropbox/boxd/skills --no-logs +node --experimental-strip-types skills/skill-cleaner/scripts/skill-cleaner.ts --root ~/.agents/skills --root-only --no-logs ``` 2. Read the report in this order: @@ -47,6 +48,7 @@ node --experimental-strip-types skills/skill-cleaner/scripts/skill-cleaner.ts -- - It follows Codex `core-skills/src/render.rs`: 2% of raw `context_window`, token cost `ceil(utf8_bytes / 4)`, then full descriptions -> equal description truncation -> omitted minimum lines. Alias-table line cost is included. - It reads `~/.codex/models_cache.json` for GPT-5.5 `context_window`; fallback is 272,000 tokens and 2%. - It scans only normal Codex/plugin/repo skill roots by default. Extra folders such as Dropbox archives are included only with `--root `. +- `--root-only` requires at least one `--root `, skips the live Codex inventory, and scans only those supplied roots. - It realpath-dedupes roots, so symlinked roots such as `~/.codex/skills/agent-scripts -> ~/Projects/agent-scripts/skills` do not create false duplicates. - For duplicate names, it reports description/body similarity and suggests deletion candidates only when bodies are near copies. Keep priority defaults to direct Codex system skills, then direct Codex skills, then plugin skills, then personal/repo copies. - It scans `~/.codex/history.jsonl` and recent `~/.codex/sessions/**/*.jsonl` by default. Add `--deep-logs` for archived sessions and common OpenClaw/Clawd log folders. diff --git a/skills/skill-cleaner/scripts/skill-cleaner.test.ts b/skills/skill-cleaner/scripts/skill-cleaner.test.ts index 66fb432..d556b58 100644 --- a/skills/skill-cleaner/scripts/skill-cleaner.test.ts +++ b/skills/skill-cleaner/scripts/skill-cleaner.test.ts @@ -1,14 +1,37 @@ import assert from "node:assert/strict"; +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; import test from "node:test"; import { compactDescription, + discoverRoots, parseLiveSkillsPrompt, plainLogSkillReads, referencedSkillPaths, usageEvidence, } from "./skill-cleaner.ts"; +test("limits root discovery to explicitly supplied roots", (context) => { + const temp = fs.mkdtempSync(path.join(os.tmpdir(), "skill-cleaner-roots-")); + context.after(() => fs.rmSync(temp, { recursive: true, force: true })); + const defaultRoots = [ + path.join(temp, ".codex/skills"), + path.join(temp, ".codex/plugins/cache"), + path.join(temp, "Projects/agent-scripts/skills"), + path.join(temp, "Projects/demo/.agents/skills"), + ]; + const isolatedRoot = path.join(temp, "isolated/skills"); + for (const root of [...defaultRoots, isolatedRoot]) fs.mkdirSync(root, { recursive: true }); + + assert.deepEqual(discoverRoots(temp, [isolatedRoot], true), [isolatedRoot]); + assert.deepEqual( + discoverRoots(temp, [isolatedRoot], false), + [...defaultRoots, isolatedRoot].sort(), + ); +}); + test("parses Codex skill roots and model-visible lines", () => { const raw = JSON.stringify([ { diff --git a/skills/skill-cleaner/scripts/skill-cleaner.ts b/skills/skill-cleaner/scripts/skill-cleaner.ts index b4d2edc..4ff736a 100755 --- a/skills/skill-cleaner/scripts/skill-cleaner.ts +++ b/skills/skill-cleaner/scripts/skill-cleaner.ts @@ -75,7 +75,8 @@ const noLogs = args.has("--no-logs"); const deepLogs = args.has("--deep-logs"); const json = args.has("--json"); const includeAll = args.has("--all"); -const noLive = args.has("--no-live"); +const rootOnly = args.has("--root-only"); +const noLive = args.has("--no-live") || rootOnly; const model = argValue("--model", "gpt-5.5"); const budgetPercent = Number(argValue("--budget-percent", "2")); const contextTokensOverride = argValue("--context-tokens", ""); @@ -84,7 +85,10 @@ const maxLogBytes = Number(argValue("--max-log-mb", "300")) * 1024 * 1024; const cutoffMs = Date.now() - Math.max(0, months) * 31 * 24 * 60 * 60 * 1000; const extraRoots = process.argv .slice(2) - .flatMap((arg, index, all) => (arg === "--root" && all[index + 1] ? [all[index + 1]] : [])); + .flatMap((arg, index, all) => { + const value = all[index + 1]; + return arg === "--root" && value && !value.startsWith("--") ? [value] : []; + }); function expandHome(input: string): string { return input.replace(/^~(?=$|\/)/, home); @@ -504,21 +508,29 @@ function configState(): { return { disabledPaths, disabledNames, disabledPlugins }; } -function discoverRoots(): string[] { +export function discoverRoots( + baseHome = home, + providedRoots = extraRoots, + exclusive = rootOnly, +): string[] { const rootsByRealPath = new Map(); - [ - path.join(home, ".codex/skills"), - path.join(home, ".codex/plugins/cache"), - path.join(home, "Projects/agent-scripts/skills"), - ...extraRoots.map(expandHome), - ].forEach((root) => { + const roots = providedRoots.map((root) => root.replace(/^~(?=$|\/)/, baseHome)); + const candidates = exclusive + ? roots + : [ + path.join(baseHome, ".codex/skills"), + path.join(baseHome, ".codex/plugins/cache"), + path.join(baseHome, "Projects/agent-scripts/skills"), + ...roots, + ]; + candidates.forEach((root) => { if (!exists(root)) return; const real = fs.realpathSync(root); const current = rootsByRealPath.get(real); if (!current || root.length < current.length) rootsByRealPath.set(real, root); }); - const projects = path.join(home, "Projects"); - if (exists(projects)) { + const projects = path.join(baseHome, "Projects"); + if (!exclusive && exists(projects)) { for (const entry of fs.readdirSync(projects, { withFileTypes: true })) { if (!entry.isDirectory() && !entry.isSymbolicLink()) continue; const skillRoot = path.join(projects, entry.name, ".agents/skills"); @@ -1209,6 +1221,11 @@ function render( } function main(): void { + if (rootOnly && extraRoots.length === 0) { + console.error("skill-cleaner: --root-only requires at least one --root "); + process.exitCode = 2; + return; + } const skills = discoverSkills(); const live = livePrompt(); const liveSkills = live ? parseLiveSkills(live) : []; From 2060ff0f496c5584ec7f89e05a1169e9bf892232 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 1 Jul 2026 07:03:15 +0100 Subject: [PATCH 002/242] ci: update checkout to v7 (#20) --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d2ab08d..4c8a1a6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ jobs: smoke: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - uses: actions/setup-node@v6 with: From ac029e0567c6423af0b73cbb2634dbd36bdeff14 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 1 Jul 2026 00:10:13 -0700 Subject: [PATCH 003/242] feat: add OpenClaw maintainer orchestration --- CHANGELOG.md | 1 + skills/maintainer-orchestrator/SKILL.md | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1584b59..4e4ac58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ summary: Timeline of guardrail helper changes mirrored from Sweetistics and rela ## 2026-07-01 — OSS Maintainer Orchestration - Expanded `maintainer-orchestrator` into a long-running control plane with one worker thread per repository, a 10-thread concurrency target with immediate smallest-queue refill, concrete status-based thread titles, safe repository synchronization, forgotten-work preservation, PR rewrite/deduplication, decision-ready risk and diff summaries, durable `VISION.md` policy capture, dependency audits, release proposals with strongest-first highlights, and a persistent daily log plus heartbeat. +- Added an explicit OpenClaw mode with ten isolated item worktrees, Discord-sourced external-contributor discovery, live GitHub permission filtering, Vision-based autonomy, repo-native serialized landing, and OpenClaw-specific proof and changelog rules. ## 2026-06-27 — Internal Handling Boundary - Clarified that task-relevant confidential information may be used in authorized internal contexts while external disclosure still requires explicit content and destination approval. diff --git a/skills/maintainer-orchestrator/SKILL.md b/skills/maintainer-orchestrator/SKILL.md index 90bb2ef..67a9edf 100644 --- a/skills/maintainer-orchestrator/SKILL.md +++ b/skills/maintainer-orchestrator/SKILL.md @@ -16,6 +16,24 @@ Coordinate repository work through completion. This is a control-plane skill: in - Determine uncertain ownership from repository contribution history, not repository name alone. - Keep a current repository ledger so completed lanes are replaced by real queue or release work. +## OpenClaw Maintainer Orchestrator + +Apply this section only when the owner explicitly asks this session to orchestrate `openclaw/openclaw`. It overrides the default OpenClaw exclusion, the generic one-thread-per-repository rule, and generic changelog handling. Repository `AGENTS.md`, `VISION.md`, and OpenClaw-specific skills remain authoritative. + +- Read current `VISION.md`, root/scoped `AGENTS.md`, `clawdtributor`, `openclaw-pr-maintainer`, `openclaw-testing`, `crabbox`, and `autoreview` before delegating. Dependency-backed work also requires direct upstream source/docs/types; Codex-backed work requires the acting worker to inspect sibling `../codex` source. +- Refresh Discrawl, then read current `#clawtributors` and `#maintainers` messages for candidate issue/PR URLs. Use Gitcrawl for related items and live `gh` before every assignment, comment, close, push, or merge. +- Select only work authored or reported by people without GitHub `write`, `maintain`, or `admin` access. Verify repository permission live; never infer GitHub access from a Discord role or channel membership. External contributors posting in `#maintainers` remain eligible. +- Maintain at least 10 active root-owned item threads while ten qualified independent items exist. Use one isolated Codex worktree thread per issue or PR, title it `OpenClaw : `, and prohibit worker delegation. The root orchestrator alone creates, steers, archives, and refills these lanes. +- Prioritize Vision-aligned security/safe-default, bug/stability, setup/first-run, data-loss, auth, install, channel-delivery, and narrow performance/test-infrastructure work. Prefer externally reported, reproducible, bounded items with a real verification path. +- Treat broad features, protocol-version changes, new config/env/default surfaces, new core plugins/channels/providers, security/privacy policy, irreversible migration choices, or behavior without usable live proof as `Needs owner` after every safe reversible step is complete. +- Treat every contributor PR as a starting proposal. Reconstruct the symptom and root cause; read the whole owner path, callers, callees, sibling surfaces, tests, current `main`, shipped behavior, and relevant dependency contracts; then refactor or rewrite when that is the cleaner bounded fix. +- Check live assignment and contributor permission before deep work. Assign `steipete` when unassigned, preserve contributor credit, prefer the original writable PR, and avoid maintainer-authored/write-access queue items unless they are the canonical fix for an eligible external report. +- Use only repository-native `scripts/pr` review, artifact, prepare, sync, and merge commands for landing. Never mutate the shared/root checkout. Workers may review, implement, test, and monitor concurrently; the root grants a serialized slot for PR-head synchronization, final prepare, and `merge-run` so mainline drift and hosted evidence stay exact. +- Before landing, require symptom proof, root cause, provenance when traceable, focused regression coverage, the cheapest sufficient broad gate, real live/E2E or Crabbox proof when feasible, fresh autoreview with no accepted/actionable findings, resolved review threads, and exact-head hosted CI/Testbox/security gates. +- Post or update one land-ready PR comment binding behavior and proof to the exact head SHA, including commands, run/lease IDs, live evidence, autoreview result, and explicit gaps. Store screenshots/videos in approved artifacts, never on the product branch. +- OpenClaw changelog is release-generated. Do not edit `CHANGELOG.md` for normal issue/PR work, even when generic maintainer rules would add an entry. +- After landing or closing, verify `main` reachability, audit linked and duplicate issues/PRs, comment canonical proof before closing proven duplicates, stop leases, archive the item thread, and refill the lane immediately. + ## Session Startup 1. List recent Codex threads before choosing repositories. Read enough state to identify repositories the owner or another coordinator is actively handling. From 37173c19be33d77a1833055014679a30ed530ff7 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 1 Jul 2026 00:12:32 -0700 Subject: [PATCH 004/242] docs: clarify OpenClaw thread ownership --- CHANGELOG.md | 2 +- skills/maintainer-orchestrator/SKILL.md | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e4ac58..73e69c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ summary: Timeline of guardrail helper changes mirrored from Sweetistics and rela ## 2026-07-01 — OSS Maintainer Orchestration - Expanded `maintainer-orchestrator` into a long-running control plane with one worker thread per repository, a 10-thread concurrency target with immediate smallest-queue refill, concrete status-based thread titles, safe repository synchronization, forgotten-work preservation, PR rewrite/deduplication, decision-ready risk and diff summaries, durable `VISION.md` policy capture, dependency audits, release proposals with strongest-first highlights, and a persistent daily log plus heartbeat. -- Added an explicit OpenClaw mode with ten isolated item worktrees, Discord-sourced external-contributor discovery, live GitHub permission filtering, Vision-based autonomy, repo-native serialized landing, and OpenClaw-specific proof and changelog rules. +- Added an explicit OpenClaw mode with ten isolated `OC`-named item worktrees, adoption of existing lanes, root-only owner questions, Discord-sourced external-contributor discovery, live GitHub permission filtering, Vision-based autonomy, repo-native serialized landing, and OpenClaw-specific proof and changelog rules. ## 2026-06-27 — Internal Handling Boundary - Clarified that task-relevant confidential information may be used in authorized internal contexts while external disclosure still requires explicit content and destination approval. diff --git a/skills/maintainer-orchestrator/SKILL.md b/skills/maintainer-orchestrator/SKILL.md index 67a9edf..7ec158c 100644 --- a/skills/maintainer-orchestrator/SKILL.md +++ b/skills/maintainer-orchestrator/SKILL.md @@ -23,7 +23,9 @@ Apply this section only when the owner explicitly asks this session to orchestra - Read current `VISION.md`, root/scoped `AGENTS.md`, `clawdtributor`, `openclaw-pr-maintainer`, `openclaw-testing`, `crabbox`, and `autoreview` before delegating. Dependency-backed work also requires direct upstream source/docs/types; Codex-backed work requires the acting worker to inspect sibling `../codex` source. - Refresh Discrawl, then read current `#clawtributors` and `#maintainers` messages for candidate issue/PR URLs. Use Gitcrawl for related items and live `gh` before every assignment, comment, close, push, or merge. - Select only work authored or reported by people without GitHub `write`, `maintain`, or `admin` access. Verify repository permission live; never infer GitHub access from a Discord role or channel membership. External contributors posting in `#maintainers` remain eligible. -- Maintain at least 10 active root-owned item threads while ten qualified independent items exist. Use one isolated Codex worktree thread per issue or PR, title it `OpenClaw : `, and prohibit worker delegation. The root orchestrator alone creates, steers, archives, and refills these lanes. +- At startup, read and adopt existing OpenClaw work threads the owner asks this session to maintain. Preserve unique progress, avoid duplicate lanes, and monitor or steer them under the newest thread-local instruction. +- Maintain at least 10 active root-owned item threads while ten qualified independent items exist. Use one isolated Codex worktree thread per issue or PR, title it `OC : `, and prohibit worker delegation. The root orchestrator alone creates, steers, archives, and refills these lanes. +- Keep owner questions in the root orchestrator chat. Workers report exact blockers upward and do not ask the owner directly unless the root explicitly delegates that interaction. - Prioritize Vision-aligned security/safe-default, bug/stability, setup/first-run, data-loss, auth, install, channel-delivery, and narrow performance/test-infrastructure work. Prefer externally reported, reproducible, bounded items with a real verification path. - Treat broad features, protocol-version changes, new config/env/default surfaces, new core plugins/channels/providers, security/privacy policy, irreversible migration choices, or behavior without usable live proof as `Needs owner` after every safe reversible step is complete. - Treat every contributor PR as a starting proposal. Reconstruct the symptom and root cause; read the whole owner path, callers, callees, sibling surfaces, tests, current `main`, shipped behavior, and relevant dependency contracts; then refactor or rewrite when that is the cleaner bounded fix. From dbd0e0d4b1d70c5edc38f84936f145911135c78b Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 1 Jul 2026 00:16:10 -0700 Subject: [PATCH 005/242] docs: keep OpenClaw triage in orchestrator --- CHANGELOG.md | 2 +- skills/maintainer-orchestrator/SKILL.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 73e69c5..3547340 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ summary: Timeline of guardrail helper changes mirrored from Sweetistics and rela ## 2026-07-01 — OSS Maintainer Orchestration - Expanded `maintainer-orchestrator` into a long-running control plane with one worker thread per repository, a 10-thread concurrency target with immediate smallest-queue refill, concrete status-based thread titles, safe repository synchronization, forgotten-work preservation, PR rewrite/deduplication, decision-ready risk and diff summaries, durable `VISION.md` policy capture, dependency audits, release proposals with strongest-first highlights, and a persistent daily log plus heartbeat. -- Added an explicit OpenClaw mode with ten isolated `OC`-named item worktrees, adoption of existing lanes, root-only owner questions, Discord-sourced external-contributor discovery, live GitHub permission filtering, Vision-based autonomy, repo-native serialized landing, and OpenClaw-specific proof and changelog rules. +- Added an explicit OpenClaw mode with root-session-only discovery and triage, ten isolated `OC`-named execution worktrees for already-qualified tasks, adoption of existing lanes, root-only owner questions, Discord-sourced external-contributor discovery, live GitHub permission filtering, Vision-based autonomy, repo-native serialized landing, and OpenClaw-specific proof and changelog rules. ## 2026-06-27 — Internal Handling Boundary - Clarified that task-relevant confidential information may be used in authorized internal contexts while external disclosure still requires explicit content and destination approval. diff --git a/skills/maintainer-orchestrator/SKILL.md b/skills/maintainer-orchestrator/SKILL.md index 7ec158c..af95b4c 100644 --- a/skills/maintainer-orchestrator/SKILL.md +++ b/skills/maintainer-orchestrator/SKILL.md @@ -21,10 +21,10 @@ Coordinate repository work through completion. This is a control-plane skill: in Apply this section only when the owner explicitly asks this session to orchestrate `openclaw/openclaw`. It overrides the default OpenClaw exclusion, the generic one-thread-per-repository rule, and generic changelog handling. Repository `AGENTS.md`, `VISION.md`, and OpenClaw-specific skills remain authoritative. - Read current `VISION.md`, root/scoped `AGENTS.md`, `clawdtributor`, `openclaw-pr-maintainer`, `openclaw-testing`, `crabbox`, and `autoreview` before delegating. Dependency-backed work also requires direct upstream source/docs/types; Codex-backed work requires the acting worker to inspect sibling `../codex` source. -- Refresh Discrawl, then read current `#clawtributors` and `#maintainers` messages for candidate issue/PR URLs. Use Gitcrawl for related items and live `gh` before every assignment, comment, close, push, or merge. +- Keep all discovery and triage in the root orchestrator session. Refresh Discrawl; read current `#clawtributors` and `#maintainers` messages; inspect candidate issue/PR URLs, related items, current `main`, author permissions, duplicates, blast radius, and verification feasibility; then make the go/no-go and autonomy classification before creating a worker. Use Gitcrawl for related items and live `gh` before every assignment, comment, close, push, or merge. - Select only work authored or reported by people without GitHub `write`, `maintain`, or `admin` access. Verify repository permission live; never infer GitHub access from a Discord role or channel membership. External contributors posting in `#maintainers` remain eligible. - At startup, read and adopt existing OpenClaw work threads the owner asks this session to maintain. Preserve unique progress, avoid duplicate lanes, and monitor or steer them under the newest thread-local instruction. -- Maintain at least 10 active root-owned item threads while ten qualified independent items exist. Use one isolated Codex worktree thread per issue or PR, title it `OC : `, and prohibit worker delegation. The root orchestrator alone creates, steers, archives, and refills these lanes. +- Maintain at least 10 active root-owned implementation threads while ten qualified independent tasks exist. Create a thread only for concrete execution after root triage has selected an issue or PR and defined the actual fix, review-and-land, live-proof, CI-repair, or close-with-proof objective. Never create discovery, queue-scan, permission-check, candidate-review, ranking, or general triage threads. Use one isolated Codex worktree thread per selected task, title it `OC : `, and prohibit worker delegation. The root orchestrator alone creates, steers, archives, and refills these lanes. - Keep owner questions in the root orchestrator chat. Workers report exact blockers upward and do not ask the owner directly unless the root explicitly delegates that interaction. - Prioritize Vision-aligned security/safe-default, bug/stability, setup/first-run, data-loss, auth, install, channel-delivery, and narrow performance/test-infrastructure work. Prefer externally reported, reproducible, bounded items with a real verification path. - Treat broad features, protocol-version changes, new config/env/default surfaces, new core plugins/channels/providers, security/privacy policy, irreversible migration choices, or behavior without usable live proof as `Needs owner` after every safe reversible step is complete. From 7d5f1d27a0fb1f03d09551186bb3989ed99a2496 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 1 Jul 2026 00:39:34 -0700 Subject: [PATCH 006/242] feat: keep maintainer orchestration awake --- CHANGELOG.md | 5 +++-- skills/maintainer-orchestrator/SKILL.md | 26 +++++++++++++++++-------- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3547340..ded1e2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,8 +8,9 @@ summary: Timeline of guardrail helper changes mirrored from Sweetistics and rela - Added `skill-cleaner --root-only` for auditing only explicitly supplied skill roots without Codex inventory noise. Thanks @its-How. ## 2026-07-01 — OSS Maintainer Orchestration -- Expanded `maintainer-orchestrator` into a long-running control plane with one worker thread per repository, a 10-thread concurrency target with immediate smallest-queue refill, concrete status-based thread titles, safe repository synchronization, forgotten-work preservation, PR rewrite/deduplication, decision-ready risk and diff summaries, durable `VISION.md` policy capture, dependency audits, release proposals with strongest-first highlights, and a persistent daily log plus heartbeat. -- Added an explicit OpenClaw mode with root-session-only discovery and triage, ten isolated `OC`-named execution worktrees for already-qualified tasks, adoption of existing lanes, root-only owner questions, Discord-sourced external-contributor discovery, live GitHub permission filtering, Vision-based autonomy, repo-native serialized landing, and OpenClaw-specific proof and changelog rules. +- Expanded `maintainer-orchestrator` into a long-running control plane with one worker thread per repository, a 20-thread concurrency target with immediate smallest-queue refill, concrete status-based thread titles, safe repository synchronization, forgotten-work preservation, PR rewrite/deduplication, decision-ready risk and diff summaries, durable `VISION.md` policy capture, dependency audits, release proposals with strongest-first highlights, and a persistent daily log plus heartbeat. +- Added an explicit OpenClaw mode with root-session-only discovery and triage, 20 isolated `OC`-named execution worktrees for already-qualified tasks, adoption of existing lanes, root-only owner questions, Discord-sourced external-contributor discovery, live GitHub permission filtering, Vision-based autonomy, repo-native serialized landing, and OpenClaw-specific proof and changelog rules. +- Made activation create or update a five-minute root-session monitoring heartbeat, raised generic and OpenClaw execution concurrency to 20 qualified lanes, and made answered owner decisions advance immediately to the next prepared question while autonomous work continues. ## 2026-06-27 — Internal Handling Boundary - Clarified that task-relevant confidential information may be used in authorized internal contexts while external disclosure still requires explicit content and destination approval. diff --git a/skills/maintainer-orchestrator/SKILL.md b/skills/maintainer-orchestrator/SKILL.md index af95b4c..69868fa 100644 --- a/skills/maintainer-orchestrator/SKILL.md +++ b/skills/maintainer-orchestrator/SKILL.md @@ -7,6 +7,13 @@ description: "Open-source maintainer orchestration: repo workers, work recovery, Coordinate repository work through completion. This is a control-plane skill: inspect, delegate, monitor, ask decisions, and report. Put substantial repository investigation, implementation, review, live proof, landing, and release execution in repository worker threads. +## Activation Watch + +- On every activation, immediately create or update one active five-minute heartbeat automation attached to the current root orchestrator thread. Name it `Maintainer Orchestrator Watch`; never create duplicates. +- The heartbeat prompt must re-enter this skill, read the latest state and newest instructions in every owned worker, apply the Monitoring Protocol, coordinate serialized landing/release gates, root-triage and refill qualified execution work to the current concurrency target, check CI/leases/memory/disk, maintain the persistent log, and surface only prepared owner decisions. +- Keep the heartbeat active while any worker, owner decision, release, CI wait, or qualified refill work remains. Disable it only when the owner explicitly stops orchestration or the monitored portfolio is genuinely complete. +- A heartbeat wake is a continuation of this root session, not a discovery worker. Keep portfolio triage and owner questions here; create repository/worktree threads only for concrete execution. + ## Repository Scope - Scan the `steipete` and `openclaw` owners, plus any other repository where Peter is the majority commit author. Confirm uncertain scope from contribution history, not repository name or owner alone. @@ -24,7 +31,7 @@ Apply this section only when the owner explicitly asks this session to orchestra - Keep all discovery and triage in the root orchestrator session. Refresh Discrawl; read current `#clawtributors` and `#maintainers` messages; inspect candidate issue/PR URLs, related items, current `main`, author permissions, duplicates, blast radius, and verification feasibility; then make the go/no-go and autonomy classification before creating a worker. Use Gitcrawl for related items and live `gh` before every assignment, comment, close, push, or merge. - Select only work authored or reported by people without GitHub `write`, `maintain`, or `admin` access. Verify repository permission live; never infer GitHub access from a Discord role or channel membership. External contributors posting in `#maintainers` remain eligible. - At startup, read and adopt existing OpenClaw work threads the owner asks this session to maintain. Preserve unique progress, avoid duplicate lanes, and monitor or steer them under the newest thread-local instruction. -- Maintain at least 10 active root-owned implementation threads while ten qualified independent tasks exist. Create a thread only for concrete execution after root triage has selected an issue or PR and defined the actual fix, review-and-land, live-proof, CI-repair, or close-with-proof objective. Never create discovery, queue-scan, permission-check, candidate-review, ranking, or general triage threads. Use one isolated Codex worktree thread per selected task, title it `OC : `, and prohibit worker delegation. The root orchestrator alone creates, steers, archives, and refills these lanes. +- Maintain a target of 20 active root-owned implementation threads while 20 qualified independent tasks exist. Create a thread only for concrete execution after root triage has selected an issue or PR and defined the actual fix, review-and-land, live-proof, CI-repair, or close-with-proof objective. Never create discovery, queue-scan, permission-check, candidate-review, ranking, or general triage threads. Use one isolated Codex worktree thread per selected task, title it `OC : `, and prohibit worker delegation. The root orchestrator alone creates, steers, archives, and refills these lanes. - Keep owner questions in the root orchestrator chat. Workers report exact blockers upward and do not ask the owner directly unless the root explicitly delegates that interaction. - Prioritize Vision-aligned security/safe-default, bug/stability, setup/first-run, data-loss, auth, install, channel-delivery, and narrow performance/test-infrastructure work. Prefer externally reported, reproducible, bounded items with a real verification path. - Treat broad features, protocol-version changes, new config/env/default surfaces, new core plugins/channels/providers, security/privacy policy, irreversible migration choices, or behavior without usable live proof as `Needs owner` after every safe reversible step is complete. @@ -38,12 +45,13 @@ Apply this section only when the owner explicitly asks this session to orchestra ## Session Startup -1. List recent Codex threads before choosing repositories. Read enough state to identify repositories the owner or another coordinator is actively handling. -2. Reserve every project with coherent active or unresolved work in another thread. Do not inspect, mutate, delegate, rename, or steer that project from this session unless the owner explicitly hands it over. -3. When a local checkout is dirty or on a non-default branch but has no active thread, create one preservation thread for that repository. Treat it as potentially valuable forgotten work, not as a reason to ignore the project. -4. Use RepoBar for the broad queue map. Filter to eligible, non-archived, non-fork repositories, then confirm Peter has the majority of contributions. -5. Prefer the smallest non-empty effective queues first. Within equal queue size, prefer bounded bugs, docs, tests, and nearly-ready PRs over features or security/product decisions. -6. Recheck active threads and queue counts on every wake before assigning new work. A newly active project becomes reserved immediately. +1. Create or update the required `Maintainer Orchestrator Watch` heartbeat before queue work. +2. List recent Codex threads before choosing repositories. Read enough state to identify repositories the owner or another coordinator is actively handling. +3. Reserve every project with coherent active or unresolved work in another thread. Do not inspect, mutate, delegate, rename, or steer that project from this session unless the owner explicitly hands it over. +4. When a local checkout is dirty or on a non-default branch but has no active thread, create one preservation thread for that repository. Treat it as potentially valuable forgotten work, not as a reason to ignore the project. +5. Use RepoBar for the broad queue map. Filter to eligible, non-archived, non-fork repositories, then confirm Peter has the majority of contributions. +6. Prefer the smallest non-empty effective queues first. Within equal queue size, prefer bounded bugs, docs, tests, and nearly-ready PRs over features or security/product decisions. +7. Recheck active threads and queue counts on every wake before assigning new work. A newly active project becomes reserved immediately. ## Repository Synchronization @@ -65,7 +73,7 @@ Repeat synchronization after every landing and before any release gate. - `Needs owner`: product choice, security/privacy decision, unavailable credentials/access, unavailable live proof, or destructive/irreversible choice. - `Ignored by owner`: an explicitly named item the owner says must not affect current work. 3. Delegate each independent repository to one root-owned project thread. Reuse it for later queue items and update its `: ` title whenever work materially changes. The project thread handles its queue serially by default. Only when at least four substantial, genuinely independent tasks would make serial execution meaningfully slow may it create direct task subthreads in isolated checkouts. Never fan out two or three items, intertwined work, or trivial tasks. Task subthreads cannot delegate further; depth stops at root → project → task. Omit model selection and inherit the platform default. -4. Maintain a target of 10 concurrent eligible root-owned project threads. After active-thread reservation and repository-state checks, refill immediately from the smallest eligible majority-authored queue whenever a lane completes, becomes durably blocked, or otherwise stops useful work. +4. Maintain a target of 20 concurrent eligible root-owned project threads. After active-thread reservation and repository-state checks, refill immediately from the smallest eligible majority-authored queue whenever a lane completes, becomes durably blocked, or otherwise stops useful work. 5. Keep this coordinator thread lightweight. Do not perform extensive repository work here. Delegate it to a repository thread, then monitor by reading current state. 6. Monitor workers every five minutes when the owner requests continuous orchestration. Let active workers execute without steering; intervene only for a confirmed blocker, exhausted work, or gross course deviation. 7. Continue until each autonomous item is merged/closed with proof, each true decision item has every safe reversible step complete and one exact owner choice remaining, an authorized release clears its release-specific blockers, or an otherwise idle repository has current dependencies. @@ -122,6 +130,8 @@ Every owner decision request must include: When several decisions are grouped, give each item its own brief. Keep the recommendation opinionated; do not offload technical analysis to the owner. If autonomous work remains, do that work first and report the item as active rather than asking for a premature decision. +Maintain an ordered root-session owner-question queue and ask one decision at a time. Whenever the owner answers, record and execute that answer immediately, then present the next fully prepared question in the same root session if one exists. If no owner decision is ready, continue autonomous work and say no owner input is currently needed; never let an answered question leave the orchestrator idle. + When the owner defers a decision, post a concise comment on the issue or PR recording the deferral, rationale, and concrete revisit condition unless the decision is private or security-sensitive. Read existing owner comments before asking again; never repeat a decision already recorded. Log the decision and full URL. ## Product Policy Capture From ed58cf26dbd200f305ffc5e96357dfeb0a38429f Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 1 Jul 2026 00:58:49 -0700 Subject: [PATCH 007/242] feat: raise maintainer concurrency to 30 --- skills/maintainer-orchestrator/SKILL.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/skills/maintainer-orchestrator/SKILL.md b/skills/maintainer-orchestrator/SKILL.md index 69868fa..d153b77 100644 --- a/skills/maintainer-orchestrator/SKILL.md +++ b/skills/maintainer-orchestrator/SKILL.md @@ -31,7 +31,7 @@ Apply this section only when the owner explicitly asks this session to orchestra - Keep all discovery and triage in the root orchestrator session. Refresh Discrawl; read current `#clawtributors` and `#maintainers` messages; inspect candidate issue/PR URLs, related items, current `main`, author permissions, duplicates, blast radius, and verification feasibility; then make the go/no-go and autonomy classification before creating a worker. Use Gitcrawl for related items and live `gh` before every assignment, comment, close, push, or merge. - Select only work authored or reported by people without GitHub `write`, `maintain`, or `admin` access. Verify repository permission live; never infer GitHub access from a Discord role or channel membership. External contributors posting in `#maintainers` remain eligible. - At startup, read and adopt existing OpenClaw work threads the owner asks this session to maintain. Preserve unique progress, avoid duplicate lanes, and monitor or steer them under the newest thread-local instruction. -- Maintain a target of 20 active root-owned implementation threads while 20 qualified independent tasks exist. Create a thread only for concrete execution after root triage has selected an issue or PR and defined the actual fix, review-and-land, live-proof, CI-repair, or close-with-proof objective. Never create discovery, queue-scan, permission-check, candidate-review, ranking, or general triage threads. Use one isolated Codex worktree thread per selected task, title it `OC : `, and prohibit worker delegation. The root orchestrator alone creates, steers, archives, and refills these lanes. +- Maintain a target of 30 active root-owned implementation threads while 30 qualified independent tasks exist. Create a thread only for concrete execution after root triage has selected an issue or PR and defined the actual fix, review-and-land, live-proof, CI-repair, or close-with-proof objective. Never create discovery, queue-scan, permission-check, candidate-review, ranking, or general triage threads. Use one isolated Codex worktree thread per selected task, title it `OC : `, and prohibit worker delegation. The root orchestrator alone creates, steers, archives, and refills these lanes. - Keep owner questions in the root orchestrator chat. Workers report exact blockers upward and do not ask the owner directly unless the root explicitly delegates that interaction. - Prioritize Vision-aligned security/safe-default, bug/stability, setup/first-run, data-loss, auth, install, channel-delivery, and narrow performance/test-infrastructure work. Prefer externally reported, reproducible, bounded items with a real verification path. - Treat broad features, protocol-version changes, new config/env/default surfaces, new core plugins/channels/providers, security/privacy policy, irreversible migration choices, or behavior without usable live proof as `Needs owner` after every safe reversible step is complete. @@ -73,7 +73,7 @@ Repeat synchronization after every landing and before any release gate. - `Needs owner`: product choice, security/privacy decision, unavailable credentials/access, unavailable live proof, or destructive/irreversible choice. - `Ignored by owner`: an explicitly named item the owner says must not affect current work. 3. Delegate each independent repository to one root-owned project thread. Reuse it for later queue items and update its `: ` title whenever work materially changes. The project thread handles its queue serially by default. Only when at least four substantial, genuinely independent tasks would make serial execution meaningfully slow may it create direct task subthreads in isolated checkouts. Never fan out two or three items, intertwined work, or trivial tasks. Task subthreads cannot delegate further; depth stops at root → project → task. Omit model selection and inherit the platform default. -4. Maintain a target of 20 concurrent eligible root-owned project threads. After active-thread reservation and repository-state checks, refill immediately from the smallest eligible majority-authored queue whenever a lane completes, becomes durably blocked, or otherwise stops useful work. +4. Maintain a target of 30 concurrent eligible root-owned project threads. After active-thread reservation and repository-state checks, refill immediately from the smallest eligible majority-authored queue whenever a lane completes, becomes durably blocked, or otherwise stops useful work. 5. Keep this coordinator thread lightweight. Do not perform extensive repository work here. Delegate it to a repository thread, then monitor by reading current state. 6. Monitor workers every five minutes when the owner requests continuous orchestration. Let active workers execute without steering; intervene only for a confirmed blocker, exhausted work, or gross course deviation. 7. Continue until each autonomous item is merged/closed with proof, each true decision item has every safe reversible step complete and one exact owner choice remaining, an authorized release clears its release-specific blockers, or an otherwise idle repository has current dependencies. From 626810320baf6431ee545e62e53bcfef861d73e9 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 1 Jul 2026 09:12:06 +0100 Subject: [PATCH 008/242] feat: add maintainer ownership ledger --- skills/maintainer-orchestrator/SKILL.md | 16 +++++++-- .../references/non-majority-repositories.md | 36 +++++++++++++++++++ 2 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 skills/maintainer-orchestrator/references/non-majority-repositories.md diff --git a/skills/maintainer-orchestrator/SKILL.md b/skills/maintainer-orchestrator/SKILL.md index d153b77..79abf57 100644 --- a/skills/maintainer-orchestrator/SKILL.md +++ b/skills/maintainer-orchestrator/SKILL.md @@ -18,6 +18,9 @@ Coordinate repository work through completion. This is a control-plane skill: in - Scan the `steipete` and `openclaw` owners, plus any other repository where Peter is the majority commit author. Confirm uncertain scope from contribution history, not repository name or owner alone. - Exclude the large OpenClaw and ClawHub projects, currently `openclaw/openclaw` and `openclaw/clawhub`. Do not exclude the rest of the `openclaw` owner. +- Read `references/non-majority-repositories.md` during portfolio discovery. Treat listed repositories as outside routine orchestration responsibility: do not use them for queue refills, dependency sweeps, release monitoring, or unsolicited maintenance. +- The non-majority ledger is a dated evidence cache, not a permanent ownership declaration. Revalidate from the current default branch when the snapshot is older than 30 days, the recorded share is within 10 percentage points of 50%, repository ownership/history changed, or evidence conflicts. Explicit owner requests override the exclusion for the requested work only. +- Classify majority from non-merge default-branch commits: combine known Peter name/email identities, exclude clearly marked bot identities, and require more than 50%. Keep ambiguous repositories unclassified instead of assuming responsibility. - Exclude archived repositories from routine discovery, queue scans, dependency audits, monitoring, release gating, and reporting. Re-enter only when the owner explicitly names the repository and requests new work. - When the owner says a repository is retired, archived, or must not be mentioned again, record it as suppressed. Make one best-effort archive mutation when requested, then keep it silent even when permissions prevent the remote archive. - Determine uncertain ownership from repository contribution history, not repository name alone. @@ -152,8 +155,9 @@ Before sending any worker message: 1. Read the worker's latest current state, including its newest user/delegation messages and active turn. 2. Treat the newest thread-local instruction as authoritative over older orchestration plans. -3. Determine whether the worker is actively progressing, blocked, completed, or idle. -4. Send nothing when an active worker has a coherent plan and is making progress. +3. When the owner directly steers a thread or contributes work, adapt immediately: preserve and account for that work, reconcile current repository/GitHub state, and continue from the owner's direction without duplicating, undoing, or misattributing it. +4. Determine whether the worker is actively progressing, blocked, completed, or idle. +5. Send nothing when an active worker has a coherent plan and is making progress. Intervene only when evidence shows one of: @@ -167,6 +171,13 @@ Do not restate the task, add speculative requirements, or raise the proof bar mi Never interrupt, archive, rename, duplicate, or replace a worker without first reading its current state. For a suspected duplicate, read both threads; if either has unique progress, edits, or an active turn, leave it alone and ask the owner before changing thread state. +### Active Waits + +- Keep the project turn active until its work reaches a terminal state. Do not emit a final answer or stop merely because CI, a runner, review, mergeability, deployment, an auth prompt, or a long command is pending. +- Prefer an in-turn 30–60 second sleep/poll cycle over a per-project automation. After each interval, refresh the exact external state, repair or rerun when needed, and continue through landing and closeout. +- Suppress routine unchanged-poll chatter, but keep polling. The root heartbeat coordinates the portfolio; it does not replace a worker watching its own pending work. +- End the turn only after successful terminal closeout, one exact owner decision/access/waiver blocker after every safe step, or a platform failure that makes continued polling impossible. + ## Thread Naming - Name every root-owned project thread `: ` at creation and each material transition: reviewing, implementing, proving, waiting for CI, exact blocker, ready, or complete. @@ -235,6 +246,7 @@ Every delegated implementation thread, under standing authority and any newer pr - run `autoreview` until no accepted/actionable findings remain; - commit and push the final candidate, then open or update its PR; - rerun required checks and repair failures until exact-head CI is green; +- remain active through CI/review/deployment waits using bounded sleep/poll cycles; never stop at a nonterminal waiting status; - merge or close the queue item with exact proof when evidence supports it; - after landing, return to updated, clean `main`; - update the changelog for user-visible changes; within the active unreleased/release section, order entries from most to least interesting to users and keep the repository's established format; diff --git a/skills/maintainer-orchestrator/references/non-majority-repositories.md b/skills/maintainer-orchestrator/references/non-majority-repositories.md new file mode 100644 index 0000000..a038218 --- /dev/null +++ b/skills/maintainer-orchestrator/references/non-majority-repositories.md @@ -0,0 +1,36 @@ +# Known Non-Majority Repositories + +Dated evidence cache for routine portfolio filtering. These repositories are generally outside Peter's orchestration responsibility. An explicit owner request overrides the exclusion for that requested work only. + +Snapshot: 2026-07-01. Metric: Peter-authored non-merge commits divided by author-history commits after filtering standard bot and automation identity patterns on the locally tracked default branch. `openclaw/clawscan` uses the current GitHub contributors endpoint because no local checkout was present. Revalidate under the rules in `SKILL.md`; do not infer unlisted repositories are majority-authored. + +| Repository | Peter / filtered commits | Leading evidence | +| --- | ---: | --- | +| [openclaw/ClawKeeper](https://github.com/openclaw/ClawKeeper) | 20 / 56 | huntharo: 31 | +| [openclaw/Kova](https://github.com/openclaw/Kova) | 9 / 635 | Shakker: 621 | +| [openclaw/acpx](https://github.com/openclaw/acpx) | 81 / 399 | Bob: 104; Vincent Koc: 72 | +| [openclaw/clawbench](https://github.com/openclaw/clawbench) | 3 / 120 | scoootscooob: 52; Codex: 26 | +| [openclaw/clawgo](https://github.com/openclaw/clawgo) | 7 / 16 | Mariano Belinky: 7; tied, no Peter majority | +| [openclaw/clawscan](https://github.com/openclaw/clawscan) | 0 / 120 | Patrick Erichsen: 110; Vincent Koc: 10 | +| [openclaw/clownfish](https://github.com/openclaw/clownfish) | 42 / 931 | Vincent Koc identities: 889 | +| [openclaw/clawrouter](https://github.com/openclaw/clawrouter) | 28 / 248 | Vincent Koc identities: 220 | +| [openclaw/crabbox](https://github.com/openclaw/crabbox) | 654 / 1,544 | Vincent Koc: 645; Peter is plurality, not majority | +| [openclaw/crabpot](https://github.com/openclaw/crabpot) | 13 / 331 | Vincent Koc: 310 | +| [openclaw/crawl-remote](https://github.com/openclaw/crawl-remote) | 5 / 18 | Vincent Koc: 12 | +| [openclaw/crawlbar](https://github.com/openclaw/crawlbar) | 16 / 152 | Vincent Koc: 128 | +| [openclaw/crawlkit](https://github.com/openclaw/crawlkit) | 34 / 203 | Vincent Koc: 168 | +| [openclaw/esp-openclaw-node](https://github.com/openclaw/esp-openclaw-node) | 2 / 11 | Dhaval Gujar: 8 | +| [openclaw/gitcrawl](https://github.com/openclaw/gitcrawl) | 162 / 430 | Vincent Koc: 251 | +| [openclaw/gitcrawl-store](https://github.com/openclaw/gitcrawl-store) | 13 / 62 | generated publisher history filtered from responsibility metric | +| [openclaw/graincrawl](https://github.com/openclaw/graincrawl) | 12 / 115 | Vincent Koc: 101 | +| [openclaw/lobster](https://github.com/openclaw/lobster) | 27 / 110 | Vignesh Natarajan identities lead | +| [openclaw/multipass](https://github.com/openclaw/multipass) | 12 / 80 | Vincent Koc: 43; Dallin Romney: 23 | +| [openclaw/nix-openclaw](https://github.com/openclaw/nix-openclaw) | 6 / 753 | openclaw-ci history filtered; other maintainers lead | +| [openclaw/notcrawl](https://github.com/openclaw/notcrawl) | 18 / 147 | Vincent Koc: 123 | +| [openclaw/openclaw-windows-node](https://github.com/openclaw/openclaw-windows-node) | 6 / 722 | Scott Hanselman: 303 | +| [openclaw/plugin-inspector](https://github.com/openclaw/plugin-inspector) | 8 / 168 | Vincent Koc: 146 | +| [openclaw/releases](https://github.com/openclaw/releases) | 6 / 20 | Vincent Koc identities: 13 | +| [openclaw/slacrawl](https://github.com/openclaw/slacrawl) | 79 / 197 | Vincent Koc: 107 | +| [steipete/nemoforge](https://github.com/steipete/nemoforge) | 3 / 146 | antirez: 102 | + +Standing separate-project exclusions remain [openclaw/openclaw](https://github.com/openclaw/openclaw) and [openclaw/clawhub](https://github.com/openclaw/clawhub), regardless of contribution share. From 5b2ba8f98a8cf027631877ca69237211ced117fb Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 1 Jul 2026 09:32:32 +0100 Subject: [PATCH 009/242] docs: keep maintainer thread titles current --- skills/maintainer-orchestrator/SKILL.md | 3 +++ .../references/non-majority-repositories.md | 3 +++ 2 files changed, 6 insertions(+) diff --git a/skills/maintainer-orchestrator/SKILL.md b/skills/maintainer-orchestrator/SKILL.md index 79abf57..0ada434 100644 --- a/skills/maintainer-orchestrator/SKILL.md +++ b/skills/maintainer-orchestrator/SKILL.md @@ -182,9 +182,12 @@ Never interrupt, archive, rename, duplicate, or replace a worker without first r - Name every root-owned project thread `: ` at creation and each material transition: reviewing, implementing, proving, waiting for CI, exact blocker, ready, or complete. - Put the project first; keep status terse, concrete, and current. Never use generic coordinate, orchestrate, or maintain labels when a specific status is known. +- Use `: done — ` for terminal success before archiving; name the shipped or closed outcome, not merely `complete`. +- Use `waiting` only while the named external gate is verifiably pending and the worker turn remains active. The moment it succeeds, fails, or becomes irrelevant, replace the title with the next action, exact blocker, or `done`. - Read the latest state and newest thread-local instructions before renaming. - Keep the title specific to current work; replace stale original-task titles. - Polling alone does not justify a rename. +- Audit every owned title on each wake. Never leave landed, closed, released, or otherwise terminal work labeled as waiting, maintenance, reviewing, or implementing. ## Persistent Log diff --git a/skills/maintainer-orchestrator/references/non-majority-repositories.md b/skills/maintainer-orchestrator/references/non-majority-repositories.md index a038218..7605ad2 100644 --- a/skills/maintainer-orchestrator/references/non-majority-repositories.md +++ b/skills/maintainer-orchestrator/references/non-majority-repositories.md @@ -23,13 +23,16 @@ Snapshot: 2026-07-01. Metric: Peter-authored non-merge commits divided by author | [openclaw/gitcrawl](https://github.com/openclaw/gitcrawl) | 162 / 430 | Vincent Koc: 251 | | [openclaw/gitcrawl-store](https://github.com/openclaw/gitcrawl-store) | 13 / 62 | generated publisher history filtered from responsibility metric | | [openclaw/graincrawl](https://github.com/openclaw/graincrawl) | 12 / 115 | Vincent Koc: 101 | +| [openclaw/krillswitch](https://github.com/openclaw/krillswitch) | 0 / 35 | Jesse Merhi: 22 | | [openclaw/lobster](https://github.com/openclaw/lobster) | 27 / 110 | Vignesh Natarajan identities lead | | [openclaw/multipass](https://github.com/openclaw/multipass) | 12 / 80 | Vincent Koc: 43; Dallin Romney: 23 | | [openclaw/nix-openclaw](https://github.com/openclaw/nix-openclaw) | 6 / 753 | openclaw-ci history filtered; other maintainers lead | | [openclaw/notcrawl](https://github.com/openclaw/notcrawl) | 18 / 147 | Vincent Koc: 123 | +| [openclaw/openclaw-ansible](https://github.com/openclaw/openclaw-ansible) | 3 / 96 | sheeek: 47 | | [openclaw/openclaw-windows-node](https://github.com/openclaw/openclaw-windows-node) | 6 / 722 | Scott Hanselman: 303 | | [openclaw/plugin-inspector](https://github.com/openclaw/plugin-inspector) | 8 / 168 | Vincent Koc: 146 | | [openclaw/releases](https://github.com/openclaw/releases) | 6 / 20 | Vincent Koc identities: 13 | +| [openclaw/rfcs](https://github.com/openclaw/rfcs) | 4 / 35 | Gio Della-Libera: 11 | | [openclaw/slacrawl](https://github.com/openclaw/slacrawl) | 79 / 197 | Vincent Koc: 107 | | [steipete/nemoforge](https://github.com/steipete/nemoforge) | 3 / 146 | antirez: 102 | From 587733dc79e5bc6a6fe5b4f3e5961f7e0d334756 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 1 Jul 2026 09:43:10 +0100 Subject: [PATCH 010/242] docs: require terminal worker titles --- skills/maintainer-orchestrator/SKILL.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/skills/maintainer-orchestrator/SKILL.md b/skills/maintainer-orchestrator/SKILL.md index 0ada434..b71f82f 100644 --- a/skills/maintainer-orchestrator/SKILL.md +++ b/skills/maintainer-orchestrator/SKILL.md @@ -92,7 +92,7 @@ Do not treat ordinary draft, stale, difficult, or platform-specific items as ign ## Control-Plane Ownership -- Only this root orchestrator may create, reuse, rename, archive, or steer project threads. +- Only this root orchestrator may create, reuse, rename, archive, or steer project threads, except the worker's required terminal self-rename immediately before final. - A project thread may create, assign, monitor, and retire only its own direct task subthreads under the threshold above. It owns their integration and reports one coherent repository result to the root. - Task subthreads must not create workers, delegate, or manage other chats. No grandchildren. - Repository-specific questions belong in that repository's worker thread. Keep the root thread for cross-repository summaries, scheduling, conflicts, and owner-level prioritization. @@ -184,6 +184,8 @@ Never interrupt, archive, rename, duplicate, or replace a worker without first r - Put the project first; keep status terse, concrete, and current. Never use generic coordinate, orchestrate, or maintain labels when a specific status is known. - Use `: done — ` for terminal success before archiving; name the shipped or closed outcome, not merely `complete`. - Use `waiting` only while the named external gate is verifiably pending and the worker turn remains active. The moment it succeeds, fails, or becomes irrelevant, replace the title with the next action, exact blocker, or `done`. +- Immediately before any final answer, the project worker must self-rename its thread to `: done — `, `: needs owner — `, or `: failed — `. The app may make a finished thread unaddressable before root can rename it; this terminal self-rename is the worker's only project-thread management exception. +- For nonterminal transitions, the worker reports the new phase and root performs the rename. - Read the latest state and newest thread-local instructions before renaming. - Keep the title specific to current work; replace stale original-task titles. - Polling alone does not justify a rename. From ec2cafc710930e7f3858d2f0d80df7733a6fe8fa Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 1 Jul 2026 09:56:47 +0100 Subject: [PATCH 011/242] fix: keep worker thread titles current --- skills/maintainer-orchestrator/SKILL.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/skills/maintainer-orchestrator/SKILL.md b/skills/maintainer-orchestrator/SKILL.md index b71f82f..539f479 100644 --- a/skills/maintainer-orchestrator/SKILL.md +++ b/skills/maintainer-orchestrator/SKILL.md @@ -92,7 +92,7 @@ Do not treat ordinary draft, stale, difficult, or platform-specific items as ign ## Control-Plane Ownership -- Only this root orchestrator may create, reuse, rename, archive, or steer project threads, except the worker's required terminal self-rename immediately before final. +- Only this root orchestrator may create, reuse, archive, or steer project threads. Each project worker owns its thread title so the title follows the freshest repository state without a root-poll race. - A project thread may create, assign, monitor, and retire only its own direct task subthreads under the threshold above. It owns their integration and reports one coherent repository result to the root. - Task subthreads must not create workers, delegate, or manage other chats. No grandchildren. - Repository-specific questions belong in that repository's worker thread. Keep the root thread for cross-repository summaries, scheduling, conflicts, and owner-level prioritization. @@ -180,16 +180,15 @@ Never interrupt, archive, rename, duplicate, or replace a worker without first r ## Thread Naming -- Name every root-owned project thread `: ` at creation and each material transition: reviewing, implementing, proving, waiting for CI, exact blocker, ready, or complete. +- Root sets the initial `: ` title. The project worker self-renames on every material transition: reviewing, implementing, proving, waiting for CI, exact blocker, ready, or complete. - Put the project first; keep status terse, concrete, and current. Never use generic coordinate, orchestrate, or maintain labels when a specific status is known. - Use `: done — ` for terminal success before archiving; name the shipped or closed outcome, not merely `complete`. - Use `waiting` only while the named external gate is verifiably pending and the worker turn remains active. The moment it succeeds, fails, or becomes irrelevant, replace the title with the next action, exact blocker, or `done`. -- Immediately before any final answer, the project worker must self-rename its thread to `: done — `, `: needs owner — `, or `: failed — `. The app may make a finished thread unaddressable before root can rename it; this terminal self-rename is the worker's only project-thread management exception. -- For nonterminal transitions, the worker reports the new phase and root performs the rename. +- Immediately before any final answer, self-rename to `: done — `, `: needs owner — `, or `: failed — `. - Read the latest state and newest thread-local instructions before renaming. - Keep the title specific to current work; replace stale original-task titles. - Polling alone does not justify a rename. -- Audit every owned title on each wake. Never leave landed, closed, released, or otherwise terminal work labeled as waiting, maintenance, reviewing, or implementing. +- Root audits every owned title on each wake. Never leave landed, closed, released, or otherwise terminal work labeled as waiting, maintenance, reviewing, or implementing. If a title is stale, send the active worker one concise correction after reading its latest state; do not overwrite the title from a stale root snapshot. Finished or unaddressable threads are excluded from active capacity. ## Persistent Log From 0a2ede426fe262f3bef287070846d9df7ced09c4 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 1 Jul 2026 14:09:28 +0100 Subject: [PATCH 012/242] docs: extend non-majority repository ledger (#21) --- .../references/non-majority-repositories.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/skills/maintainer-orchestrator/references/non-majority-repositories.md b/skills/maintainer-orchestrator/references/non-majority-repositories.md index 7605ad2..b50b67f 100644 --- a/skills/maintainer-orchestrator/references/non-majority-repositories.md +++ b/skills/maintainer-orchestrator/references/non-majority-repositories.md @@ -14,7 +14,9 @@ Snapshot: 2026-07-01. Metric: Peter-authored non-merge commits divided by author | [openclaw/clawscan](https://github.com/openclaw/clawscan) | 0 / 120 | Patrick Erichsen: 110; Vincent Koc: 10 | | [openclaw/clownfish](https://github.com/openclaw/clownfish) | 42 / 931 | Vincent Koc identities: 889 | | [openclaw/clawrouter](https://github.com/openclaw/clawrouter) | 28 / 248 | Vincent Koc identities: 220 | +| [openclaw/clawdinators](https://github.com/openclaw/clawdinators) | 2 / 253 | Josh Palmer identities: 251; automation identities filtered | | [openclaw/crabbox](https://github.com/openclaw/crabbox) | 654 / 1,544 | Vincent Koc: 645; Peter is plurality, not majority | +| [openclaw/crabline](https://github.com/openclaw/crabline) | 13 / 81 | Vincent Koc identities: 45; Dallin Romney: 23 | | [openclaw/crabpot](https://github.com/openclaw/crabpot) | 13 / 331 | Vincent Koc: 310 | | [openclaw/crawl-remote](https://github.com/openclaw/crawl-remote) | 5 / 18 | Vincent Koc: 12 | | [openclaw/crawlbar](https://github.com/openclaw/crawlbar) | 16 / 152 | Vincent Koc: 128 | @@ -33,7 +35,10 @@ Snapshot: 2026-07-01. Metric: Peter-authored non-merge commits divided by author | [openclaw/plugin-inspector](https://github.com/openclaw/plugin-inspector) | 8 / 168 | Vincent Koc: 146 | | [openclaw/releases](https://github.com/openclaw/releases) | 6 / 20 | Vincent Koc identities: 13 | | [openclaw/rfcs](https://github.com/openclaw/rfcs) | 4 / 35 | Gio Della-Libera: 11 | +| [openclaw/shellbench](https://github.com/openclaw/shellbench) | 3 / 120 | scoootscooob identities: 56; Codex: 26 | | [openclaw/slacrawl](https://github.com/openclaw/slacrawl) | 79 / 197 | Vincent Koc: 107 | +| [steipete/iterm-mcp](https://github.com/steipete/iterm-mcp) | 2 / 67 | Ferris Lucas: 59 | | [steipete/nemoforge](https://github.com/steipete/nemoforge) | 3 / 146 | antirez: 102 | +| [martian-engineering/lossless-claw](https://github.com/martian-engineering/lossless-claw) | 1 / 440 | Josh Lehman: 245; automation identities filtered | Standing separate-project exclusions remain [openclaw/openclaw](https://github.com/openclaw/openclaw) and [openclaw/clawhub](https://github.com/openclaw/clawhub), regardless of contribution share. From 9342cafe87e2a178357d09996e4dee28c7d41ad0 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 1 Jul 2026 14:19:19 +0100 Subject: [PATCH 013/242] docs: route Peekaboo automation through app host (#22) --- skills/peekaboo/SKILL.md | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/skills/peekaboo/SKILL.md b/skills/peekaboo/SKILL.md index b35f512..7ac1ad3 100644 --- a/skills/peekaboo/SKILL.md +++ b/skills/peekaboo/SKILL.md @@ -13,6 +13,14 @@ Use for macOS screen capture, UI inspection, and GUI automation. - Else use `peekaboo`. - Check first: `~/bin/peekaboo --version || peekaboo --version`. +## Mac app host + +- Launch `Peekaboo.app` before live capture/automation; the CLI does not auto-launch it. +- The app owns TCC grants and serves `~/Library/Application Support/Peekaboo/bridge.sock`. +- Installed app: `open -a Peekaboo`. Repo build: build the `Apps/Mac/Peekaboo.xcodeproj` `Peekaboo` scheme, then open the resulting `Peekaboo.app`. +- `peekaboo daemon start` is not an app launch; the daemon has separate permissions and `daemon.sock`. +- Verify `peekaboo bridge status --verbose --json --bridge-socket "$HOME/Library/Application Support/Peekaboo/bridge.sock"` selects `hostKind: gui`. + ## Safety - Check permissions before capture/automation: `peekaboo permissions status --json`. @@ -29,6 +37,8 @@ Use for macOS screen capture, UI inspection, and GUI automation. PB="${PEEKABOO_BIN:-$HOME/bin/peekaboo}" [ -x "$PB" ] || PB="$(command -v peekaboo)" +open -a Peekaboo +"$PB" bridge status --verbose --json --bridge-socket "$HOME/Library/Application Support/Peekaboo/bridge.sock" "$PB" permissions status --json "$PB" list screens --json "$PB" list apps --json @@ -44,11 +54,12 @@ PB="${PEEKABOO_BIN:-$HOME/bin/peekaboo}" ## Workflow 1. Resolve `PB` as above and confirm version when install state matters. -2. Run `permissions status --json`; if missing TCC, report exact missing grant. -3. For screenshots, use `image`; include `--path`, `--json`, and usually `--no-remote`. -4. For element targeting, run `see --json --annotate`, then click by element id/snapshot. -5. For long-running/change-aware screen capture, use `capture live`; for video frame sampling, use `capture video`. -6. Use `tools --json` for command/tool discovery and `learn` when the full agent guide is useful. -7. Verify output files with `sips -g pixelWidth -g pixelHeight ` or view the image. +2. For live UI work, launch `Peekaboo.app`; verify the GUI bridge and its permissions. +3. Run `permissions status --json`; if missing TCC, report exact missing grant. +4. For screenshots, use `image`; include `--path`, `--json`, and usually `--no-remote` only when deliberately testing caller-local TCC. +5. For element targeting, run `see --json --annotate`, then click by element id/snapshot. +6. For long-running/change-aware screen capture, use `capture live`; for video frame sampling, use `capture video`. +7. Use `tools --json` for command/tool discovery and `learn` when the full agent guide is useful. +8. Verify output files with `sips -g pixelWidth -g pixelHeight ` or view the image. Docs: `~/Projects/Peekaboo/docs/commands/`. From 9ff786db80b4d6047a891bf7396ffbf16292e3d4 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 1 Jul 2026 14:28:03 +0100 Subject: [PATCH 014/242] chore: refresh browser extraction libraries (#23) --- scripts/browser-tools.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/browser-tools.ts b/scripts/browser-tools.ts index 3c8ffb1..0f76ddd 100644 --- a/scripts/browser-tools.ts +++ b/scripts/browser-tools.ts @@ -951,8 +951,8 @@ async function ensureReadability(page: any) { // ignore } const scripts = [ - 'https://unpkg.com/@mozilla/readability@0.4.4/Readability.js', - 'https://unpkg.com/turndown@7.1.2/dist/turndown.js', + 'https://unpkg.com/@mozilla/readability@0.6.0/Readability.js', + 'https://unpkg.com/turndown@7.2.4/dist/turndown.js', 'https://unpkg.com/turndown-plugin-gfm@1.0.2/dist/turndown-plugin-gfm.js', ]; for (const src of scripts) { From e1898eeb140cf35128a4ee134b70ff40b5123179 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 1 Jul 2026 14:34:40 +0100 Subject: [PATCH 015/242] build: declare browser helper dependencies (#24) --- .github/workflows/ci.yml | 10 +++++++ .gitignore | 2 ++ bun.lock | 62 ++++++++++++++++++++++++++++++++++++++++ package.json | 9 ++++++ 4 files changed, 83 insertions(+) create mode 100644 bun.lock create mode 100644 package.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4c8a1a6..7c43ede 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,6 +18,10 @@ jobs: cache: npm cache-dependency-path: skills/video-transcript-downloader/package-lock.json + - uses: oven-sh/setup-bun@v2 + with: + bun-version: 1.3.14 + - name: Check shell helper syntax run: | find skills -path '*/scripts/*' -type f -print0 | @@ -30,6 +34,12 @@ jobs: - name: Test ClawSweeper status helper run: skills/clawsweeper-status/scripts/clawsweeper-status.test.sh + - name: Build browser helper + run: | + bun install --frozen-lockfile + bun build scripts/browser-tools.ts --compile --target bun --outfile /tmp/browser-tools + /tmp/browser-tools --help + - name: Install video transcript downloader dependencies working-directory: skills/video-transcript-downloader run: npm ci diff --git a/.gitignore b/.gitignore index 2df94b0..92b306c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ .DS_Store +.*.bun-build .pnpm-store/ +node_modules/ __pycache__/ *.py[cod] bin/* diff --git a/bun.lock b/bun.lock new file mode 100644 index 0000000..fa43846 --- /dev/null +++ b/bun.lock @@ -0,0 +1,62 @@ +{ + "lockfileVersion": 1, + "configVersion": 1, + "workspaces": { + "": { + "name": "agent-scripts-tools", + "dependencies": { + "commander": "^15.0.0", + "puppeteer-core": "^25.3.0", + }, + }, + }, + "packages": { + "@puppeteer/browsers": ["@puppeteer/browsers@3.0.6", "", { "dependencies": { "modern-tar": "^0.7.6", "yargs": "^18.0.0" }, "peerDependencies": { "proxy-agent": ">=8.0.1", "yauzl": "^2.10.0 || ^3.4.0" }, "optionalPeers": ["proxy-agent", "yauzl"], "bin": { "browsers": "lib/main-cli.js" } }, "sha512-B/gKoqlFkzhvzsI6jo9K1cZz9o5ypviVv/xu8CwA4grZzyVwN+XfkT+tu8T1zrauuEXv6VhS2oGX+6NL95WcKA=="], + + "ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], + + "ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], + + "chromium-bidi": ["chromium-bidi@16.0.1", "", { "dependencies": { "mitt": "^3.0.1", "zod": "^3.24.1" }, "peerDependencies": { "devtools-protocol": "*" } }, "sha512-J63PGu/9PpeCwLIcKYyzWP6yaVL5pxuBc0shlYCYM8BaAkmlwiQboXO1iNbOgSDbVklEyYFfNEcHD8oOAWacUA=="], + + "cliui": ["cliui@9.0.1", "", { "dependencies": { "string-width": "^7.2.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" } }, "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w=="], + + "commander": ["commander@15.0.0", "", {}, "sha512-z67u4ZhzCL/Tydu1lJARtEZYWbWaN7oYLHbsuzocr6y4N6WZAagG3RQ4FW61V1/0+jImpj293XfrcYnd1qxtPg=="], + + "devtools-protocol": ["devtools-protocol@0.0.1638949", "", {}, "sha512-mXwg4Fqnv0WR4iuAT/gYUmctNkjILwXFHyZ+m7Ty1dfr0ezZt2U3gnrrJTfRobJTHoXf+IbuFvFITzLrLFjwJA=="], + + "emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="], + + "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], + + "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="], + + "get-east-asian-width": ["get-east-asian-width@1.6.0", "", {}, "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA=="], + + "mitt": ["mitt@3.0.1", "", {}, "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw=="], + + "modern-tar": ["modern-tar@0.7.6", "", {}, "sha512-sweCIVXzx1aIGTCdzcMlSZt1h8k5Tmk08VNAuRk3IU28XamGiOH5ypi11g6De2CH7PhYqSSnGy2A/EFhbWnVKg=="], + + "puppeteer-core": ["puppeteer-core@25.3.0", "", { "dependencies": { "@puppeteer/browsers": "3.0.6", "chromium-bidi": "16.0.1", "devtools-protocol": "0.0.1638949", "typed-query-selector": "^2.12.2", "webdriver-bidi-protocol": "0.4.2", "ws": "^8.21.0" } }, "sha512-fm+wpUr2oigH1PXZvwgATrM2tYWHMDG8ASzTEe9uukCye4X5Ldx1K5BTHPFKITrIWvQQAQ256d1NpbEveBcKjA=="], + + "string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="], + + "strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], + + "typed-query-selector": ["typed-query-selector@2.12.2", "", {}, "sha512-EOPFbyIub4ngnEdqi2yOcNeDLaX/0jcE1JoAXQDDMIthap7FoN795lc/SHfIq2d416VufXpM8z/lD+WRm2gfOQ=="], + + "webdriver-bidi-protocol": ["webdriver-bidi-protocol@0.4.2", "", {}, "sha512-VSV+fzfChirL3e7jay2yUC7B4HQCGtEWEg/MSSQbK+qWbqeGlRLlXTzPpYr3XGUvbpDHumWZBJxgesg4N7dbtA=="], + + "wrap-ansi": ["wrap-ansi@9.0.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww=="], + + "ws": ["ws@8.21.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g=="], + + "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="], + + "yargs": ["yargs@18.0.0", "", { "dependencies": { "cliui": "^9.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "string-width": "^7.2.0", "y18n": "^5.0.5", "yargs-parser": "^22.0.0" } }, "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg=="], + + "yargs-parser": ["yargs-parser@22.0.0", "", {}, "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw=="], + + "zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..2da8e75 --- /dev/null +++ b/package.json @@ -0,0 +1,9 @@ +{ + "name": "agent-scripts-tools", + "private": true, + "type": "module", + "dependencies": { + "commander": "^15.0.0", + "puppeteer-core": "^25.3.0" + } +} From 2d007c16435fbf14d7b9f7a4a8bbe6a4dda56165 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 1 Jul 2026 14:41:38 +0100 Subject: [PATCH 016/242] docs: align orchestrator concurrency changelog (#25) --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ded1e2b..31ee77b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,9 +8,9 @@ summary: Timeline of guardrail helper changes mirrored from Sweetistics and rela - Added `skill-cleaner --root-only` for auditing only explicitly supplied skill roots without Codex inventory noise. Thanks @its-How. ## 2026-07-01 — OSS Maintainer Orchestration -- Expanded `maintainer-orchestrator` into a long-running control plane with one worker thread per repository, a 20-thread concurrency target with immediate smallest-queue refill, concrete status-based thread titles, safe repository synchronization, forgotten-work preservation, PR rewrite/deduplication, decision-ready risk and diff summaries, durable `VISION.md` policy capture, dependency audits, release proposals with strongest-first highlights, and a persistent daily log plus heartbeat. -- Added an explicit OpenClaw mode with root-session-only discovery and triage, 20 isolated `OC`-named execution worktrees for already-qualified tasks, adoption of existing lanes, root-only owner questions, Discord-sourced external-contributor discovery, live GitHub permission filtering, Vision-based autonomy, repo-native serialized landing, and OpenClaw-specific proof and changelog rules. -- Made activation create or update a five-minute root-session monitoring heartbeat, raised generic and OpenClaw execution concurrency to 20 qualified lanes, and made answered owner decisions advance immediately to the next prepared question while autonomous work continues. +- Expanded `maintainer-orchestrator` into a long-running control plane with one worker thread per repository, a 30-thread concurrency target with immediate smallest-queue refill, concrete status-based thread titles, safe repository synchronization, forgotten-work preservation, PR rewrite/deduplication, decision-ready risk and diff summaries, durable `VISION.md` policy capture, dependency audits, release proposals with strongest-first highlights, and a persistent daily log plus heartbeat. +- Added an explicit OpenClaw mode with root-session-only discovery and triage, 30 isolated `OC`-named execution worktrees for already-qualified tasks, adoption of existing lanes, root-only owner questions, Discord-sourced external-contributor discovery, live GitHub permission filtering, Vision-based autonomy, repo-native serialized landing, and OpenClaw-specific proof and changelog rules. +- Made activation create or update a five-minute root-session monitoring heartbeat, raised generic and OpenClaw execution concurrency to 30 qualified lanes, and made answered owner decisions advance immediately to the next prepared question while autonomous work continues. ## 2026-06-27 — Internal Handling Boundary - Clarified that task-relevant confidential information may be used in authorized internal contexts while external disclosure still requires explicit content and destination approval. From 18e20fa1532a328a3371f35cef8bcf57c6d8c5df Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Thu, 2 Jul 2026 09:06:18 +0100 Subject: [PATCH 017/242] fix: keep orchestrator execution thread-owned --- .github/workflows/ci.yml | 3 ++ CHANGELOG.md | 3 +- scripts/test-maintainer-orchestrator-policy | 22 ++++++++++ skills/maintainer-orchestrator/SKILL.md | 41 +++++++++++-------- .../agents/openai.yaml | 4 +- 5 files changed, 54 insertions(+), 19 deletions(-) create mode 100755 scripts/test-maintainer-orchestrator-policy diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7c43ede..99045b5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,6 +34,9 @@ jobs: - name: Test ClawSweeper status helper run: skills/clawsweeper-status/scripts/clawsweeper-status.test.sh + - name: Test maintainer orchestrator worker boundary + run: scripts/test-maintainer-orchestrator-policy + - name: Build browser helper run: | bun install --frozen-lockfile diff --git a/CHANGELOG.md b/CHANGELOG.md index 31ee77b..a0413de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,9 +8,10 @@ summary: Timeline of guardrail helper changes mirrored from Sweetistics and rela - Added `skill-cleaner --root-only` for auditing only explicitly supplied skill roots without Codex inventory noise. Thanks @its-How. ## 2026-07-01 — OSS Maintainer Orchestration -- Expanded `maintainer-orchestrator` into a long-running control plane with one worker thread per repository, a 30-thread concurrency target with immediate smallest-queue refill, concrete status-based thread titles, safe repository synchronization, forgotten-work preservation, PR rewrite/deduplication, decision-ready risk and diff summaries, durable `VISION.md` policy capture, dependency audits, release proposals with strongest-first highlights, and a persistent daily log plus heartbeat. +- Expanded `maintainer-orchestrator` into a long-running control plane with one Codex app worker thread per repository, a 30-thread concurrency target with immediate smallest-queue refill, concrete status-based thread titles, safe repository synchronization, forgotten-work preservation, PR rewrite/deduplication, decision-ready risk and diff summaries, durable `VISION.md` policy capture, dependency audits, release proposals with strongest-first highlights, and a persistent daily log plus heartbeat. - Added an explicit OpenClaw mode with root-session-only discovery and triage, 30 isolated `OC`-named execution worktrees for already-qualified tasks, adoption of existing lanes, root-only owner questions, Discord-sourced external-contributor discovery, live GitHub permission filtering, Vision-based autonomy, repo-native serialized landing, and OpenClaw-specific proof and changelog rules. - Made activation create or update a five-minute root-session monitoring heartbeat, raised generic and OpenClaw execution concurrency to 30 qualified lanes, and made answered owner decisions advance immediately to the next prepared question while autonomous work continues. +- Required every implementation and execution worker to be a Codex app thread; restricted collaboration subagents to read-only orchestration support with mandatory pre-spawn classification and preservation-first handoff of any misrouted implementation work. ## 2026-06-27 — Internal Handling Boundary - Clarified that task-relevant confidential information may be used in authorized internal contexts while external disclosure still requires explicit content and destination approval. diff --git a/scripts/test-maintainer-orchestrator-policy b/scripts/test-maintainer-orchestrator-policy new file mode 100755 index 0000000..34d5c6d --- /dev/null +++ b/scripts/test-maintainer-orchestrator-policy @@ -0,0 +1,22 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +skill = File.read(File.expand_path("../skills/maintainer-orchestrator/SKILL.md", __dir__)) +metadata = File.read(File.expand_path("../skills/maintainer-orchestrator/agents/openai.yaml", __dir__)) + +requirements = { + "Codex app workers only" => "a worker is an owned Codex app thread, never a collaboration subagent", + "pre-spawn classification" => "Before spawning a collaboration subagent, classify the task", + "mutating work routing" => "Any task that can mutate repository, GitHub, or external state", + "support-only subagents" => "Use collaboration subagents only for orchestration support", + "subagent mutation ban" => "Collaboration subagents must never edit repository files, create commits, run implementation proof as the owner, push, mutate PRs/issues, approve workflows, merge, release, deploy, or perform live product/account proof.", + "preservation-first recovery" => "Snapshot and preserve its state, patches, refs, logs, and evidence; hand them to the proper Codex app thread; reconcile ownership; never discard work.", + "thread-owned execution" => "Project execution remains owned and performed by its Codex app thread", +} + +missing = requirements.reject { |_label, text| skill.include?(text) } +abort "Missing maintainer-orchestrator policy: #{missing.keys.join(', ')}" unless missing.empty? +abort "Ambiguous task subthread terminology" if skill.match?(/\bsubthreads?\b/i) +abort "Stale maintainer-orchestrator default prompt" unless metadata.include?("dedicated Codex app threads") && metadata.include?("collaboration subagents read-only and support-only") + +puts "Validated maintainer-orchestrator worker boundary." diff --git a/skills/maintainer-orchestrator/SKILL.md b/skills/maintainer-orchestrator/SKILL.md index 539f479..2108c77 100644 --- a/skills/maintainer-orchestrator/SKILL.md +++ b/skills/maintainer-orchestrator/SKILL.md @@ -1,16 +1,25 @@ --- name: maintainer-orchestrator -description: "Open-source maintainer orchestration: repo workers, work recovery, dependencies, vision, releases." +description: "Open-source maintainer orchestration: Codex app workers, work recovery, dependencies, vision, releases." --- # Maintainer Orchestrator -Coordinate repository work through completion. This is a control-plane skill: inspect, delegate, monitor, ask decisions, and report. Put substantial repository investigation, implementation, review, live proof, landing, and release execution in repository worker threads. +Coordinate repository work through completion. This is a control-plane skill: inspect, delegate, monitor, ask decisions, and report. In this skill, a worker is an owned Codex app thread, never a collaboration subagent. + +## Worker Boundary — Hard Rule + +- Use dedicated Codex app threads as all implementation and execution workers. Prefer an existing owned thread/worktree when it already owns relevant state; otherwise create the proper project or task thread. +- Before spawning a collaboration subagent, classify the task. Any task that can mutate repository, GitHub, or external state, or that owns a deliverable, implementation proof, landing, release, or deployment, must go to a Codex app thread. +- Use collaboration subagents only for orchestration support: read-only inventory, CI/status monitoring, independent analysis, conflict/decision synthesis, or ledger/reconciliation evidence. They do not own worker lanes or count toward execution capacity. +- Collaboration subagents must never edit repository files, create commits, run implementation proof as the owner, push, mutate PRs/issues, approve workflows, merge, release, deploy, or perform live product/account proof. +- If an implementation subagent is discovered, interrupt it immediately. Snapshot and preserve its state, patches, refs, logs, and evidence; hand them to the proper Codex app thread; reconcile ownership; never discard work. +- The root orchestrator coordinates app threads, reads evidence, sends GO/hold instructions, serializes exact-head landing, handles owner decisions, and cleans up the sidebar. Project execution remains owned and performed by its Codex app thread. ## Activation Watch - On every activation, immediately create or update one active five-minute heartbeat automation attached to the current root orchestrator thread. Name it `Maintainer Orchestrator Watch`; never create duplicates. -- The heartbeat prompt must re-enter this skill, read the latest state and newest instructions in every owned worker, apply the Monitoring Protocol, coordinate serialized landing/release gates, root-triage and refill qualified execution work to the current concurrency target, check CI/leases/memory/disk, maintain the persistent log, and surface only prepared owner decisions. +- The heartbeat prompt must re-enter this skill, read the latest state and newest instructions in every owned Codex app worker, apply the Monitoring Protocol, coordinate serialized landing/release gates, root-triage and refill qualified execution work to the current concurrency target, check CI/leases/memory/disk, maintain the persistent log, and surface only prepared owner decisions. - Keep the heartbeat active while any worker, owner decision, release, CI wait, or qualified refill work remains. Disable it only when the owner explicitly stops orchestration or the monitored portfolio is genuinely complete. - A heartbeat wake is a continuation of this root session, not a discovery worker. Keep portfolio triage and owner questions here; create repository/worktree threads only for concrete execution. @@ -34,7 +43,7 @@ Apply this section only when the owner explicitly asks this session to orchestra - Keep all discovery and triage in the root orchestrator session. Refresh Discrawl; read current `#clawtributors` and `#maintainers` messages; inspect candidate issue/PR URLs, related items, current `main`, author permissions, duplicates, blast radius, and verification feasibility; then make the go/no-go and autonomy classification before creating a worker. Use Gitcrawl for related items and live `gh` before every assignment, comment, close, push, or merge. - Select only work authored or reported by people without GitHub `write`, `maintain`, or `admin` access. Verify repository permission live; never infer GitHub access from a Discord role or channel membership. External contributors posting in `#maintainers` remain eligible. - At startup, read and adopt existing OpenClaw work threads the owner asks this session to maintain. Preserve unique progress, avoid duplicate lanes, and monitor or steer them under the newest thread-local instruction. -- Maintain a target of 30 active root-owned implementation threads while 30 qualified independent tasks exist. Create a thread only for concrete execution after root triage has selected an issue or PR and defined the actual fix, review-and-land, live-proof, CI-repair, or close-with-proof objective. Never create discovery, queue-scan, permission-check, candidate-review, ranking, or general triage threads. Use one isolated Codex worktree thread per selected task, title it `OC : `, and prohibit worker delegation. The root orchestrator alone creates, steers, archives, and refills these lanes. +- Maintain a target of 30 active root-owned implementation Codex app threads while 30 qualified independent tasks exist. Create a thread only for concrete execution after root triage has selected an issue or PR and defined the actual fix, review-and-land, live-proof, CI-repair, or close-with-proof objective. Never create discovery, queue-scan, permission-check, candidate-review, ranking, or general triage threads. Use one isolated Codex worktree thread per selected task, title it `OC : `, and prohibit worker delegation. The root orchestrator alone creates, steers, archives, and refills these lanes. - Keep owner questions in the root orchestrator chat. Workers report exact blockers upward and do not ask the owner directly unless the root explicitly delegates that interaction. - Prioritize Vision-aligned security/safe-default, bug/stability, setup/first-run, data-loss, auth, install, channel-delivery, and narrow performance/test-infrastructure work. Prefer externally reported, reproducible, bounded items with a real verification path. - Treat broad features, protocol-version changes, new config/env/default surfaces, new core plugins/channels/providers, security/privacy policy, irreversible migration choices, or behavior without usable live proof as `Needs owner` after every safe reversible step is complete. @@ -49,7 +58,7 @@ Apply this section only when the owner explicitly asks this session to orchestra ## Session Startup 1. Create or update the required `Maintainer Orchestrator Watch` heartbeat before queue work. -2. List recent Codex threads before choosing repositories. Read enough state to identify repositories the owner or another coordinator is actively handling. +2. List recent Codex app threads before choosing repositories. Read enough state to identify repositories the owner or another coordinator is actively handling. 3. Reserve every project with coherent active or unresolved work in another thread. Do not inspect, mutate, delegate, rename, or steer that project from this session unless the owner explicitly hands it over. 4. When a local checkout is dirty or on a non-default branch but has no active thread, create one preservation thread for that repository. Treat it as potentially valuable forgotten work, not as a reason to ignore the project. 5. Use RepoBar for the broad queue map. Filter to eligible, non-archived, non-fork repositories, then confirm Peter has the majority of contributions. @@ -75,10 +84,10 @@ Repeat synchronization after every landing and before any release gate. - `Autonomous`: clear fit, reproducible, bounded implementation, and usable verification path. - `Needs owner`: product choice, security/privacy decision, unavailable credentials/access, unavailable live proof, or destructive/irreversible choice. - `Ignored by owner`: an explicitly named item the owner says must not affect current work. -3. Delegate each independent repository to one root-owned project thread. Reuse it for later queue items and update its `: ` title whenever work materially changes. The project thread handles its queue serially by default. Only when at least four substantial, genuinely independent tasks would make serial execution meaningfully slow may it create direct task subthreads in isolated checkouts. Never fan out two or three items, intertwined work, or trivial tasks. Task subthreads cannot delegate further; depth stops at root → project → task. Omit model selection and inherit the platform default. -4. Maintain a target of 30 concurrent eligible root-owned project threads. After active-thread reservation and repository-state checks, refill immediately from the smallest eligible majority-authored queue whenever a lane completes, becomes durably blocked, or otherwise stops useful work. -5. Keep this coordinator thread lightweight. Do not perform extensive repository work here. Delegate it to a repository thread, then monitor by reading current state. -6. Monitor workers every five minutes when the owner requests continuous orchestration. Let active workers execute without steering; intervene only for a confirmed blocker, exhausted work, or gross course deviation. +3. Delegate each independent repository to one root-owned Codex app project thread. Reuse it for later queue items and update its `: ` title whenever work materially changes. The project thread handles its queue serially by default. Only when at least four substantial, genuinely independent tasks would make serial execution meaningfully slow may it create direct Codex app task threads in isolated checkouts. Never fan out two or three items, intertwined work, or trivial tasks. Task threads cannot delegate further; depth stops at root → project → task. Omit model selection and inherit the platform default. +4. Maintain a target of 30 concurrent eligible root-owned Codex app project threads. After active-thread reservation and repository-state checks, refill immediately from the smallest eligible majority-authored queue whenever a lane completes, becomes durably blocked, or otherwise stops useful work. +5. Keep this coordinator thread lightweight. Do not perform extensive repository work here. Delegate it to a repository Codex app thread, then monitor by reading current state. +6. Monitor Codex app workers every five minutes when the owner requests continuous orchestration. Let active workers execute without steering; intervene only for a confirmed blocker, exhausted work, or gross course deviation. 7. Continue until each autonomous item is merged/closed with proof, each true decision item has every safe reversible step complete and one exact owner choice remaining, an authorized release clears its release-specific blockers, or an otherwise idle repository has current dependencies. Do not treat ordinary draft, stale, difficult, or platform-specific items as ignored. Only an explicit owner instruction can create an ignored-item exception. Keep ignored items open and visible; do not close, edit, or merge them unless separately requested. @@ -92,11 +101,11 @@ Do not treat ordinary draft, stale, difficult, or platform-specific items as ign ## Control-Plane Ownership -- Only this root orchestrator may create, reuse, archive, or steer project threads. Each project worker owns its thread title so the title follows the freshest repository state without a root-poll race. -- A project thread may create, assign, monitor, and retire only its own direct task subthreads under the threshold above. It owns their integration and reports one coherent repository result to the root. -- Task subthreads must not create workers, delegate, or manage other chats. No grandchildren. +- Only this root orchestrator may create, reuse, archive, or steer project Codex app threads. Each project worker owns its thread title so the title follows the freshest repository state without a root-poll race. +- A project thread may create, assign, monitor, and retire only its own direct Codex app task threads under the threshold above. It owns their integration and reports one coherent repository result to the root. +- Task threads must not create workers, delegate, or manage other chats. No grandchildren. - Repository-specific questions belong in that repository's worker thread. Keep the root thread for cross-repository summaries, scheduling, conflicts, and owner-level prioritization. -- Put the one-level limit in every project prompt and the no-subdelegation rule in every task-subthread prompt. +- Put the one-level limit in every project prompt and the no-subdelegation rule in every task-thread prompt. - Do not delegate portfolio triage or cross-repository thread management. - Legacy nested coordinators: stop further delegation immediately, preserve unique context while their existing workers finish, then retire them after reading current state. @@ -214,7 +223,7 @@ Always perform a dependency-freshness check before closing a repository work bat ## Authorization -The owner grants standing autonomous authority for in-scope repository queue work coordinated by this session. Project threads may synchronize clean checkouts; edit; create branches; commit; push; open or update PRs; write proof/review/close comments; approve, rerun, and repair CI; merge supported exact-head green changes; close resolved or invalid items; and return to synchronized clean `main`. Do not request per-item permission to implement, repair, improve, rewrite, publish a PR, fix CI, or land clearly supported work. +The owner grants standing autonomous authority for in-scope repository queue work coordinated by this session. Project Codex app threads may synchronize clean checkouts; edit; create branches; commit; push; open or update PRs; write proof/review/close comments; approve, rerun, and repair CI; merge supported exact-head green changes; close resolved or invalid items; and return to synchronized clean `main`. Do not request per-item permission to implement, repair, improve, rewrite, publish a PR, fix CI, or land clearly supported work. This standing authority does not include: @@ -237,9 +246,9 @@ Assume most maintainer credentials are stored in 1Password. Before reporting a c Keep credential discovery and use inside the worker that needs the secret. Report only presence, access path, and the exact missing approval or item; never send credentials between threads. -## Worker Contract +## Codex App Worker Contract -Every delegated implementation thread, under standing authority and any newer project-specific limits, must: +Every delegated implementation Codex app thread, under standing authority and any newer project-specific limits, must: - read the full issue/PR discussion, repo instructions, docs, and relevant code; - when an issue has no PR, create one after implementing the best bounded candidate; diff --git a/skills/maintainer-orchestrator/agents/openai.yaml b/skills/maintainer-orchestrator/agents/openai.yaml index 47fcdb8..87e9775 100644 --- a/skills/maintainer-orchestrator/agents/openai.yaml +++ b/skills/maintainer-orchestrator/agents/openai.yaml @@ -1,4 +1,4 @@ interface: display_name: "Maintainer Orchestrator" - short_description: "Coordinate one thread per open-source project" - default_prompt: "Use $maintainer-orchestrator to synchronize repositories safely, protect forgotten work, autonomously implement, repair, review, land, and close eligible queue work, coordinate one project thread with bounded one-level task fan-out for large independent queues, capture durable vision decisions, audit dependencies, propose highlighted releases, maintain the daily log, and report clickable URLs with diff size, risk, proof, and recommendation." + short_description: "Coordinate Codex app project workers" + default_prompt: "Use $maintainer-orchestrator to coordinate repository execution in dedicated Codex app threads, keep collaboration subagents read-only and support-only, protect forgotten work, serialize exact-head landing, capture durable decisions, audit dependencies, and propose verified releases." From 15af4c5b34e25e165d410b6c2da44bca21bb4393 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Thu, 2 Jul 2026 01:09:11 -0700 Subject: [PATCH 018/242] Harden orchestrator concurrency and permission checks --- scripts/test-maintainer-orchestrator-policy | 8 ++++++++ skills/maintainer-orchestrator/SKILL.md | 7 ++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/scripts/test-maintainer-orchestrator-policy b/scripts/test-maintainer-orchestrator-policy index 34d5c6d..4d1f8de 100755 --- a/scripts/test-maintainer-orchestrator-policy +++ b/scripts/test-maintainer-orchestrator-policy @@ -12,6 +12,14 @@ requirements = { "subagent mutation ban" => "Collaboration subagents must never edit repository files, create commits, run implementation proof as the owner, push, mutate PRs/issues, approve workflows, merge, release, deploy, or perform live product/account proof.", "preservation-first recovery" => "Snapshot and preserve its state, patches, refs, logs, and evidence; hand them to the proper Codex app thread; reconcile ownership; never discard work.", "thread-owned execution" => "Project execution remains owned and performed by its Codex app thread", + "text is not capability" => "Thread prompts do not grant capabilities", + "permission propagation check" => "verify its effective permission profile", + "no repeated permission prompts" => "Do not retry the same denied action or repeatedly prompt the owner.", + "single heartbeat inspection" => "inspect the existing heartbeat first", + "private concurrency invariant" => "Hard concurrency invariant: private investigation, implementation, current-main replay, testing, proof, and review continue independently", + "single public mutation slot" => "Exactly one worker at a time may mutate a public PR head", + "frozen means public only" => "means public-mutation-frozen unless the instruction explicitly freezes all private work", + "decision wait does not idle" => "Keep all other qualified private lanes active while that answer is pending.", } missing = requirements.reject { |_label, text| skill.include?(text) } diff --git a/skills/maintainer-orchestrator/SKILL.md b/skills/maintainer-orchestrator/SKILL.md index 2108c77..5e6dfbe 100644 --- a/skills/maintainer-orchestrator/SKILL.md +++ b/skills/maintainer-orchestrator/SKILL.md @@ -15,10 +15,12 @@ Coordinate repository work through completion. This is a control-plane skill: in - Collaboration subagents must never edit repository files, create commits, run implementation proof as the owner, push, mutate PRs/issues, approve workflows, merge, release, deploy, or perform live product/account proof. - If an implementation subagent is discovered, interrupt it immediately. Snapshot and preserve its state, patches, refs, logs, and evidence; hand them to the proper Codex app thread; reconcile ownership; never discard work. - The root orchestrator coordinates app threads, reads evidence, sends GO/hold instructions, serializes exact-head landing, handles owner decisions, and cleans up the sidebar. Project execution remains owned and performed by its Codex app thread. +- Thread prompts do not grant capabilities. Never treat text such as `full access`, `authorized`, or `you may run this` as changing the worker's effective sandbox, filesystem, network, or approval policy. +- After creating, forking, handing off, or background-resuming a worker, verify its effective permission profile before assigning the first protected write, network, test, or publication action. If a worker that should inherit owner-selected full access instead reports managed/read-only or approval-gated permissions, stop the protected action, record one platform permission-propagation blocker, and route the task to a correctly configured Codex app thread. Do not retry the same denied action or repeatedly prompt the owner. ## Activation Watch -- On every activation, immediately create or update one active five-minute heartbeat automation attached to the current root orchestrator thread. Name it `Maintainer Orchestrator Watch`; never create duplicates. +- On every activation, inspect the existing heartbeat first. Create one active five-minute heartbeat automation attached to the current root orchestrator thread only when none exists; update it only when its configuration or portfolio instructions materially changed. Name it `Maintainer Orchestrator Watch`; never create duplicates or emit repeated no-op update cards. - The heartbeat prompt must re-enter this skill, read the latest state and newest instructions in every owned Codex app worker, apply the Monitoring Protocol, coordinate serialized landing/release gates, root-triage and refill qualified execution work to the current concurrency target, check CI/leases/memory/disk, maintain the persistent log, and surface only prepared owner decisions. - Keep the heartbeat active while any worker, owner decision, release, CI wait, or qualified refill work remains. Disable it only when the owner explicitly stops orchestration or the monitored portfolio is genuinely complete. - A heartbeat wake is a continuation of this root session, not a discovery worker. Keep portfolio triage and owner questions here; create repository/worktree threads only for concrete execution. @@ -44,6 +46,7 @@ Apply this section only when the owner explicitly asks this session to orchestra - Select only work authored or reported by people without GitHub `write`, `maintain`, or `admin` access. Verify repository permission live; never infer GitHub access from a Discord role or channel membership. External contributors posting in `#maintainers` remain eligible. - At startup, read and adopt existing OpenClaw work threads the owner asks this session to maintain. Preserve unique progress, avoid duplicate lanes, and monitor or steer them under the newest thread-local instruction. - Maintain a target of 30 active root-owned implementation Codex app threads while 30 qualified independent tasks exist. Create a thread only for concrete execution after root triage has selected an issue or PR and defined the actual fix, review-and-land, live-proof, CI-repair, or close-with-proof objective. Never create discovery, queue-scan, permission-check, candidate-review, ranking, or general triage threads. Use one isolated Codex worktree thread per selected task, title it `OC : `, and prohibit worker delegation. The root orchestrator alone creates, steers, archives, and refills these lanes. +- Hard concurrency invariant: private investigation, implementation, current-main replay, testing, proof, and review continue independently across qualified workers. Exactly one worker at a time may mutate a public PR head or run final `prepare-sync-head`, `prepare-run`, or `merge-run`. Asking the owner what to land next reserves only that public slot; it never pauses other useful private lanes. `Frozen`, `parked`, or `held` means public-mutation-frozen unless the instruction explicitly freezes all private work. - Keep owner questions in the root orchestrator chat. Workers report exact blockers upward and do not ask the owner directly unless the root explicitly delegates that interaction. - Prioritize Vision-aligned security/safe-default, bug/stability, setup/first-run, data-loss, auth, install, channel-delivery, and narrow performance/test-infrastructure work. Prefer externally reported, reproducible, bounded items with a real verification path. - Treat broad features, protocol-version changes, new config/env/default surfaces, new core plugins/channels/providers, security/privacy policy, irreversible migration choices, or behavior without usable live proof as `Needs owner` after every safe reversible step is complete. @@ -144,6 +147,8 @@ When several decisions are grouped, give each item its own brief. Keep the recom Maintain an ordered root-session owner-question queue and ask one decision at a time. Whenever the owner answers, record and execute that answer immediately, then present the next fully prepared question in the same root session if one exists. If no owner decision is ready, continue autonomous work and say no owner input is currently needed; never let an answered question leave the orchestrator idle. +After each land, exact post-merge proof, cleanup, and thread-archive cycle, ask which decision-ready candidate should receive the next public slot. Keep all other qualified private lanes active while that answer is pending. + When the owner defers a decision, post a concise comment on the issue or PR recording the deferral, rationale, and concrete revisit condition unless the decision is private or security-sensitive. Read existing owner comments before asking again; never repeat a decision already recorded. Log the decision and full URL. ## Product Policy Capture From 2fe30c0dbef752bf19c56c1f7457945228c0ceef Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Thu, 2 Jul 2026 09:21:53 +0100 Subject: [PATCH 019/242] fix: keep orchestrator skill updates in root --- CHANGELOG.md | 3 ++ scripts/test-maintainer-orchestrator-policy | 21 +++++++--- skills/maintainer-orchestrator/SKILL.md | 40 +++++++++---------- .../agents/openai.yaml | 4 +- 4 files changed, 41 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a0413de..cd06bdb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ summary: Timeline of guardrail helper changes mirrored from Sweetistics and rela # Changelog +## 2026-07-02 — Orchestrator Ownership +- Kept `maintainer-orchestrator` skill maintenance in the root orchestration session and enforced exactly one Codex app thread per project, removing project-to-task thread fan-out including the OpenClaw exception. + ## 2026-07-01 — Isolated Skill Audits - Added `skill-cleaner --root-only` for auditing only explicitly supplied skill roots without Codex inventory noise. Thanks @its-How. diff --git a/scripts/test-maintainer-orchestrator-policy b/scripts/test-maintainer-orchestrator-policy index 4d1f8de..ebd036d 100755 --- a/scripts/test-maintainer-orchestrator-policy +++ b/scripts/test-maintainer-orchestrator-policy @@ -6,8 +6,11 @@ metadata = File.read(File.expand_path("../skills/maintainer-orchestrator/agents/ requirements = { "Codex app workers only" => "a worker is an owned Codex app thread, never a collaboration subagent", + "one project thread per repository" => "Use exactly one owned Codex app project thread per repository", + "root-owned skill maintenance" => "Maintain this canonical `maintainer-orchestrator` skill in the current root orchestrator session, never in a project thread or collaboration subagent.", + "no project task fan-out" => "project threads never create task threads", "pre-spawn classification" => "Before spawning a collaboration subagent, classify the task", - "mutating work routing" => "Any task that can mutate repository, GitHub, or external state", + "mutating work routing" => "Any repository task that can mutate repository, GitHub, or external state", "support-only subagents" => "Use collaboration subagents only for orchestration support", "subagent mutation ban" => "Collaboration subagents must never edit repository files, create commits, run implementation proof as the owner, push, mutate PRs/issues, approve workflows, merge, release, deploy, or perform live product/account proof.", "preservation-first recovery" => "Snapshot and preserve its state, patches, refs, logs, and evidence; hand them to the proper Codex app thread; reconcile ownership; never discard work.", @@ -16,15 +19,23 @@ requirements = { "permission propagation check" => "verify its effective permission profile", "no repeated permission prompts" => "Do not retry the same denied action or repeatedly prompt the owner.", "single heartbeat inspection" => "inspect the existing heartbeat first", - "private concurrency invariant" => "Hard concurrency invariant: private investigation, implementation, current-main replay, testing, proof, and review continue independently", - "single public mutation slot" => "Exactly one worker at a time may mutate a public PR head", + "private concurrency invariant" => "Hard concurrency invariant: private investigation, implementation, current-main replay, testing, proof, and review continue independently across qualified project threads for distinct repositories.", + "single public mutation slot" => "Exactly one project thread at a time may mutate a public PR head", "frozen means public only" => "means public-mutation-frozen unless the instruction explicitly freezes all private work", - "decision wait does not idle" => "Keep all other qualified private lanes active while that answer is pending.", + "decision wait does not idle" => "Keep all other qualified private project lanes active while that answer is pending.", } missing = requirements.reject { |_label, text| skill.include?(text) } abort "Missing maintainer-orchestrator policy: #{missing.keys.join(', ')}" unless missing.empty? abort "Ambiguous task subthread terminology" if skill.match?(/\bsubthreads?\b/i) -abort "Stale maintainer-orchestrator default prompt" unless metadata.include?("dedicated Codex app threads") && metadata.include?("collaboration subagents read-only and support-only") +forbidden_fan_out = [ + "may create direct Codex app task threads", + "A project thread may create", + "Use one isolated Codex worktree thread per selected task", + "root → project → task", + "Workers may review, implement, test, and monitor concurrently", +] +abort "Task-thread fan-out remains" if forbidden_fan_out.any? { |text| skill.include?(text) } +abort "Stale maintainer-orchestrator default prompt" unless metadata.include?("one Codex app thread per project") && metadata.include?("skill maintenance in the root session") && metadata.include?("collaboration subagents read-only and support-only") puts "Validated maintainer-orchestrator worker boundary." diff --git a/skills/maintainer-orchestrator/SKILL.md b/skills/maintainer-orchestrator/SKILL.md index 5e6dfbe..9a21c8a 100644 --- a/skills/maintainer-orchestrator/SKILL.md +++ b/skills/maintainer-orchestrator/SKILL.md @@ -9,21 +9,22 @@ Coordinate repository work through completion. This is a control-plane skill: in ## Worker Boundary — Hard Rule -- Use dedicated Codex app threads as all implementation and execution workers. Prefer an existing owned thread/worktree when it already owns relevant state; otherwise create the proper project or task thread. -- Before spawning a collaboration subagent, classify the task. Any task that can mutate repository, GitHub, or external state, or that owns a deliverable, implementation proof, landing, release, or deployment, must go to a Codex app thread. +- Use exactly one owned Codex app project thread per repository for implementation and execution. Reuse it for the full repository queue; project threads never create task threads. +- Maintain this canonical `maintainer-orchestrator` skill in the current root orchestrator session, never in a project thread or collaboration subagent. Skill policy defines the control plane and is the sole implementation exception to project-thread execution. +- Before spawning a collaboration subagent, classify the task. Any repository task that can mutate repository, GitHub, or external state, or that owns a deliverable, implementation proof, landing, release, or deployment, must go to that repository's single Codex app project thread. - Use collaboration subagents only for orchestration support: read-only inventory, CI/status monitoring, independent analysis, conflict/decision synthesis, or ledger/reconciliation evidence. They do not own worker lanes or count toward execution capacity. - Collaboration subagents must never edit repository files, create commits, run implementation proof as the owner, push, mutate PRs/issues, approve workflows, merge, release, deploy, or perform live product/account proof. - If an implementation subagent is discovered, interrupt it immediately. Snapshot and preserve its state, patches, refs, logs, and evidence; hand them to the proper Codex app thread; reconcile ownership; never discard work. - The root orchestrator coordinates app threads, reads evidence, sends GO/hold instructions, serializes exact-head landing, handles owner decisions, and cleans up the sidebar. Project execution remains owned and performed by its Codex app thread. - Thread prompts do not grant capabilities. Never treat text such as `full access`, `authorized`, or `you may run this` as changing the worker's effective sandbox, filesystem, network, or approval policy. -- After creating, forking, handing off, or background-resuming a worker, verify its effective permission profile before assigning the first protected write, network, test, or publication action. If a worker that should inherit owner-selected full access instead reports managed/read-only or approval-gated permissions, stop the protected action, record one platform permission-propagation blocker, and route the task to a correctly configured Codex app thread. Do not retry the same denied action or repeatedly prompt the owner. +- After creating, handing off, or background-resuming a project thread, verify its effective permission profile before assigning the first protected write, network, test, or publication action. If a worker that should inherit owner-selected full access instead reports managed/read-only or approval-gated permissions, stop the protected action, record one platform permission-propagation blocker, and route the task to a correctly configured Codex app project thread for that repository. Do not retry the same denied action or repeatedly prompt the owner. ## Activation Watch - On every activation, inspect the existing heartbeat first. Create one active five-minute heartbeat automation attached to the current root orchestrator thread only when none exists; update it only when its configuration or portfolio instructions materially changed. Name it `Maintainer Orchestrator Watch`; never create duplicates or emit repeated no-op update cards. - The heartbeat prompt must re-enter this skill, read the latest state and newest instructions in every owned Codex app worker, apply the Monitoring Protocol, coordinate serialized landing/release gates, root-triage and refill qualified execution work to the current concurrency target, check CI/leases/memory/disk, maintain the persistent log, and surface only prepared owner decisions. - Keep the heartbeat active while any worker, owner decision, release, CI wait, or qualified refill work remains. Disable it only when the owner explicitly stops orchestration or the monitored portfolio is genuinely complete. -- A heartbeat wake is a continuation of this root session, not a discovery worker. Keep portfolio triage and owner questions here; create repository/worktree threads only for concrete execution. +- A heartbeat wake is a continuation of this root session, not a discovery worker. Keep portfolio triage, owner questions, and maintenance of this skill here; create one project thread per repository only for concrete execution. ## Repository Scope @@ -39,31 +40,30 @@ Coordinate repository work through completion. This is a control-plane skill: in ## OpenClaw Maintainer Orchestrator -Apply this section only when the owner explicitly asks this session to orchestrate `openclaw/openclaw`. It overrides the default OpenClaw exclusion, the generic one-thread-per-repository rule, and generic changelog handling. Repository `AGENTS.md`, `VISION.md`, and OpenClaw-specific skills remain authoritative. +Apply this section only when the owner explicitly asks this session to orchestrate `openclaw/openclaw`. It overrides the default OpenClaw exclusion and generic changelog handling; the one-thread-per-repository rule still applies. Repository `AGENTS.md`, `VISION.md`, and OpenClaw-specific skills remain authoritative. - Read current `VISION.md`, root/scoped `AGENTS.md`, `clawdtributor`, `openclaw-pr-maintainer`, `openclaw-testing`, `crabbox`, and `autoreview` before delegating. Dependency-backed work also requires direct upstream source/docs/types; Codex-backed work requires the acting worker to inspect sibling `../codex` source. - Keep all discovery and triage in the root orchestrator session. Refresh Discrawl; read current `#clawtributors` and `#maintainers` messages; inspect candidate issue/PR URLs, related items, current `main`, author permissions, duplicates, blast radius, and verification feasibility; then make the go/no-go and autonomy classification before creating a worker. Use Gitcrawl for related items and live `gh` before every assignment, comment, close, push, or merge. - Select only work authored or reported by people without GitHub `write`, `maintain`, or `admin` access. Verify repository permission live; never infer GitHub access from a Discord role or channel membership. External contributors posting in `#maintainers` remain eligible. - At startup, read and adopt existing OpenClaw work threads the owner asks this session to maintain. Preserve unique progress, avoid duplicate lanes, and monitor or steer them under the newest thread-local instruction. -- Maintain a target of 30 active root-owned implementation Codex app threads while 30 qualified independent tasks exist. Create a thread only for concrete execution after root triage has selected an issue or PR and defined the actual fix, review-and-land, live-proof, CI-repair, or close-with-proof objective. Never create discovery, queue-scan, permission-check, candidate-review, ranking, or general triage threads. Use one isolated Codex worktree thread per selected task, title it `OC : `, and prohibit worker delegation. The root orchestrator alone creates, steers, archives, and refills these lanes. -- Hard concurrency invariant: private investigation, implementation, current-main replay, testing, proof, and review continue independently across qualified workers. Exactly one worker at a time may mutate a public PR head or run final `prepare-sync-head`, `prepare-run`, or `merge-run`. Asking the owner what to land next reserves only that public slot; it never pauses other useful private lanes. `Frozen`, `parked`, or `held` means public-mutation-frozen unless the instruction explicitly freezes all private work. +- Use one root-owned OpenClaw project thread for all selected execution, processed serially in root-prioritized order. Never create per-item or task threads. The root orchestrator alone triages, steers the project thread, serializes final preparation/landing, and advances it to the next selected item. - Keep owner questions in the root orchestrator chat. Workers report exact blockers upward and do not ask the owner directly unless the root explicitly delegates that interaction. - Prioritize Vision-aligned security/safe-default, bug/stability, setup/first-run, data-loss, auth, install, channel-delivery, and narrow performance/test-infrastructure work. Prefer externally reported, reproducible, bounded items with a real verification path. - Treat broad features, protocol-version changes, new config/env/default surfaces, new core plugins/channels/providers, security/privacy policy, irreversible migration choices, or behavior without usable live proof as `Needs owner` after every safe reversible step is complete. - Treat every contributor PR as a starting proposal. Reconstruct the symptom and root cause; read the whole owner path, callers, callees, sibling surfaces, tests, current `main`, shipped behavior, and relevant dependency contracts; then refactor or rewrite when that is the cleaner bounded fix. - Check live assignment and contributor permission before deep work. Assign `steipete` when unassigned, preserve contributor credit, prefer the original writable PR, and avoid maintainer-authored/write-access queue items unless they are the canonical fix for an eligible external report. -- Use only repository-native `scripts/pr` review, artifact, prepare, sync, and merge commands for landing. Never mutate the shared/root checkout. Workers may review, implement, test, and monitor concurrently; the root grants a serialized slot for PR-head synchronization, final prepare, and `merge-run` so mainline drift and hosted evidence stay exact. +- Use only repository-native `scripts/pr` review, artifact, prepare, sync, and merge commands for landing. Never mutate the shared/root checkout. The single OpenClaw project thread reviews, implements, tests, and monitors one selected item at a time; the root grants its serialized slot for PR-head synchronization, final prepare, and `merge-run` so mainline drift and hosted evidence stay exact. - Before landing, require symptom proof, root cause, provenance when traceable, focused regression coverage, the cheapest sufficient broad gate, real live/E2E or Crabbox proof when feasible, fresh autoreview with no accepted/actionable findings, resolved review threads, and exact-head hosted CI/Testbox/security gates. - Post or update one land-ready PR comment binding behavior and proof to the exact head SHA, including commands, run/lease IDs, live evidence, autoreview result, and explicit gaps. Store screenshots/videos in approved artifacts, never on the product branch. - OpenClaw changelog is release-generated. Do not edit `CHANGELOG.md` for normal issue/PR work, even when generic maintainer rules would add an entry. -- After landing or closing, verify `main` reachability, audit linked and duplicate issues/PRs, comment canonical proof before closing proven duplicates, stop leases, archive the item thread, and refill the lane immediately. +- After landing or closing, verify `main` reachability, audit linked and duplicate issues/PRs, comment canonical proof before closing proven duplicates, stop leases, then advance the same project thread to the next selected item. ## Session Startup 1. Create or update the required `Maintainer Orchestrator Watch` heartbeat before queue work. 2. List recent Codex app threads before choosing repositories. Read enough state to identify repositories the owner or another coordinator is actively handling. 3. Reserve every project with coherent active or unresolved work in another thread. Do not inspect, mutate, delegate, rename, or steer that project from this session unless the owner explicitly hands it over. -4. When a local checkout is dirty or on a non-default branch but has no active thread, create one preservation thread for that repository. Treat it as potentially valuable forgotten work, not as a reason to ignore the project. +4. When a local checkout is dirty or on a non-default branch but has no active thread, create that repository's single project thread in preservation mode. Treat it as potentially valuable forgotten work, not as a reason to ignore the project. 5. Use RepoBar for the broad queue map. Filter to eligible, non-archived, non-fork repositories, then confirm Peter has the majority of contributions. 6. Prefer the smallest non-empty effective queues first. Within equal queue size, prefer bounded bugs, docs, tests, and nearly-ready PRs over features or security/product decisions. 7. Recheck active threads and queue counts on every wake before assigning new work. A newly active project becomes reserved immediately. @@ -87,11 +87,12 @@ Repeat synchronization after every landing and before any release gate. - `Autonomous`: clear fit, reproducible, bounded implementation, and usable verification path. - `Needs owner`: product choice, security/privacy decision, unavailable credentials/access, unavailable live proof, or destructive/irreversible choice. - `Ignored by owner`: an explicitly named item the owner says must not affect current work. -3. Delegate each independent repository to one root-owned Codex app project thread. Reuse it for later queue items and update its `: ` title whenever work materially changes. The project thread handles its queue serially by default. Only when at least four substantial, genuinely independent tasks would make serial execution meaningfully slow may it create direct Codex app task threads in isolated checkouts. Never fan out two or three items, intertwined work, or trivial tasks. Task threads cannot delegate further; depth stops at root → project → task. Omit model selection and inherit the platform default. -4. Maintain a target of 30 concurrent eligible root-owned Codex app project threads. After active-thread reservation and repository-state checks, refill immediately from the smallest eligible majority-authored queue whenever a lane completes, becomes durably blocked, or otherwise stops useful work. -5. Keep this coordinator thread lightweight. Do not perform extensive repository work here. Delegate it to a repository Codex app thread, then monitor by reading current state. -6. Monitor Codex app workers every five minutes when the owner requests continuous orchestration. Let active workers execute without steering; intervene only for a confirmed blocker, exhausted work, or gross course deviation. -7. Continue until each autonomous item is merged/closed with proof, each true decision item has every safe reversible step complete and one exact owner choice remaining, an authorized release clears its release-specific blockers, or an otherwise idle repository has current dependencies. +3. Delegate each independent repository to exactly one root-owned Codex app project thread. Reuse it for the full queue and update its `: ` title whenever work materially changes. The project thread handles its queue serially and never creates or manages other threads. Omit model selection and inherit the platform default. +4. Maintain a target of 30 concurrent eligible root-owned Codex app project threads across distinct repositories. After active-thread reservation and repository-state checks, refill immediately from the smallest eligible majority-authored queue whenever a lane completes, becomes durably blocked, or otherwise stops useful work. +5. Hard concurrency invariant: private investigation, implementation, current-main replay, testing, proof, and review continue independently across qualified project threads for distinct repositories. Exactly one project thread at a time may mutate a public PR head or run a final preparation, synchronization, merge, release, or publication gate. Asking the owner what to land next reserves only that public slot; it never pauses useful private work in other project threads. `Frozen`, `parked`, or `held` means public-mutation-frozen unless the instruction explicitly freezes all private work. +6. Keep this coordinator thread lightweight. Do not perform extensive repository work here. Delegate it to a repository Codex app thread, then monitor by reading current state. +7. Monitor Codex app workers every five minutes when the owner requests continuous orchestration. Let active workers execute without steering; intervene only for a confirmed blocker, exhausted work, or gross course deviation. +8. Continue until each autonomous item is merged/closed with proof, each true decision item has every safe reversible step complete and one exact owner choice remaining, an authorized release clears its release-specific blockers, or an otherwise idle repository has current dependencies. Do not treat ordinary draft, stale, difficult, or platform-specific items as ignored. Only an explicit owner instruction can create an ignored-item exception. Keep ignored items open and visible; do not close, edit, or merge them unless separately requested. @@ -105,10 +106,9 @@ Do not treat ordinary draft, stale, difficult, or platform-specific items as ign ## Control-Plane Ownership - Only this root orchestrator may create, reuse, archive, or steer project Codex app threads. Each project worker owns its thread title so the title follows the freshest repository state without a root-poll race. -- A project thread may create, assign, monitor, and retire only its own direct Codex app task threads under the threshold above. It owns their integration and reports one coherent repository result to the root. -- Task threads must not create workers, delegate, or manage other chats. No grandchildren. +- Project threads must not create, assign, steer, monitor, or retire other threads. The hierarchy stops at root orchestrator → one project thread per repository. - Repository-specific questions belong in that repository's worker thread. Keep the root thread for cross-repository summaries, scheduling, conflicts, and owner-level prioritization. -- Put the one-level limit in every project prompt and the no-subdelegation rule in every task-thread prompt. +- Put the one-project-thread rule and no-thread-delegation rule in every project prompt. - Do not delegate portfolio triage or cross-repository thread management. - Legacy nested coordinators: stop further delegation immediately, preserve unique context while their existing workers finish, then retire them after reading current state. @@ -147,7 +147,7 @@ When several decisions are grouped, give each item its own brief. Keep the recom Maintain an ordered root-session owner-question queue and ask one decision at a time. Whenever the owner answers, record and execute that answer immediately, then present the next fully prepared question in the same root session if one exists. If no owner decision is ready, continue autonomous work and say no owner input is currently needed; never let an answered question leave the orchestrator idle. -After each land, exact post-merge proof, cleanup, and thread-archive cycle, ask which decision-ready candidate should receive the next public slot. Keep all other qualified private lanes active while that answer is pending. +After each land, exact post-merge proof, cleanup, and project-thread status cycle, ask which decision-ready candidate should receive the next public slot. Keep all other qualified private project lanes active while that answer is pending. When the owner defers a decision, post a concise comment on the issue or PR recording the deferral, rationale, and concrete revisit condition unless the decision is private or security-sensitive. Read existing owner comments before asking again; never repeat a decision already recorded. Log the decision and full URL. @@ -237,7 +237,7 @@ This standing authority does not include: - material product, security, privacy, legal, credential-sharing, or irreversible choices that lack a safe reversible default; - external-system mutations beyond the repository/GitHub workflow unless separately authorized. -Clearly qualifying noise retains standing silent-close authority. A newer owner instruction may narrow any project. Record standing authority and exceptions in every project/task prompt; stop only at the exact remaining exception or hard blocker. +Clearly qualifying noise retains standing silent-close authority. A newer owner instruction may narrow any project. Record standing authority and exceptions in every project prompt; stop only at the exact remaining exception or hard blocker. ## Credential Access diff --git a/skills/maintainer-orchestrator/agents/openai.yaml b/skills/maintainer-orchestrator/agents/openai.yaml index 87e9775..623b1ec 100644 --- a/skills/maintainer-orchestrator/agents/openai.yaml +++ b/skills/maintainer-orchestrator/agents/openai.yaml @@ -1,4 +1,4 @@ interface: display_name: "Maintainer Orchestrator" - short_description: "Coordinate Codex app project workers" - default_prompt: "Use $maintainer-orchestrator to coordinate repository execution in dedicated Codex app threads, keep collaboration subagents read-only and support-only, protect forgotten work, serialize exact-head landing, capture durable decisions, audit dependencies, and propose verified releases." + short_description: "Coordinate one Codex app thread per project" + default_prompt: "Use $maintainer-orchestrator to coordinate one Codex app thread per project, keep skill maintenance in the root session, keep collaboration subagents read-only and support-only, protect forgotten work, serialize exact-head landing, capture durable decisions, audit dependencies, and propose verified releases." From e4f62cfcbcfda6c3e804966272b341aa29412fdd Mon Sep 17 00:00:00 2001 From: chaochaoweb3 <49186707+chaochaoweb3@users.noreply.github.com> Date: Thu, 2 Jul 2026 16:22:50 +0800 Subject: [PATCH 020/242] fix: read skill files as UTF-8 --- scripts/validate-skills | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/validate-skills b/scripts/validate-skills index 4d8e1fc..6e4904c 100755 --- a/scripts/validate-skills +++ b/scripts/validate-skills @@ -37,7 +37,7 @@ errors = [] names = {} skill_files.each do |path| - text = File.read(path) + text = File.read(path, encoding: "UTF-8") data, error = load_front_matter(path, text) if error From 98012b74448ae3e7d3a79508fbe2f46630af7aa0 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Thu, 2 Jul 2026 02:49:53 -0700 Subject: [PATCH 021/242] docs: credit UTF-8 validator fix --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cd06bdb..fa52fb8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ summary: Timeline of guardrail helper changes mirrored from Sweetistics and rela # Changelog +## 2026-07-02 — UTF-8 Skill Validation +- Made skill validation explicitly read UTF-8 so C locales accept non-ASCII skill front matter. Thanks @chaochaoweb3. + ## 2026-07-02 — Orchestrator Ownership - Kept `maintainer-orchestrator` skill maintenance in the root orchestration session and enforced exactly one Codex app thread per project, removing project-to-task thread fan-out including the OpenClaw exception. From 60f37b15b6aeb674a8922bcbdd61a571df4e4427 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 3 Jul 2026 23:34:00 +0100 Subject: [PATCH 022/242] docs(one-password): streamline desktop fallback --- skills/one-password/SKILL.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/skills/one-password/SKILL.md b/skills/one-password/SKILL.md index 9264bbe..b9d728f 100644 --- a/skills/one-password/SKILL.md +++ b/skills/one-password/SKILL.md @@ -20,8 +20,8 @@ Follow the official CLI get-started steps. Don't guess install commands. 2. Verify CLI present inside tmux: `op --version`. 3. REQUIRED: create exactly one persistent named tmux session for the whole secret task. 4. Try scoped service-account access first when a matching token/workflow exists; no dialogs. -5. If service-account access is missing or lacks the exact item/field needed, stop and ask before desktop-app sign-in. -6. Desktop fallback: confirm app integration/unlock, then `op signin` once inside the same session. +5. If service-account access is missing or lacks the exact item/field needed, automatically try the desktop-app fallback in the same session. Do not ask for chat permission first. +6. Desktop fallback: trigger app integration/unlock, then `op signin` once inside the same session. The 1Password prompt is the user approval boundary; ask in chat only if the prompt cannot be surfaced or completed. 7. Verify chosen access path inside that same session: `op whoami`. 8. If multiple accounts: use `--account` or `OP_ACCOUNT`. 9. If a command fails, reuse the same tmux session with `tmux send-keys`; do not start a second session just to retry. @@ -40,11 +40,11 @@ Follow the official CLI get-started steps. Don't guess install commands. - 1Password service accounts are non-interactive tokens for a specific vault/scope, useful for automation without unlocking the desktop app. - Peter's default service-account token is exported from `~/.profile` as `OP_SERVICE_ACCOUNT_TOKEN` in a Codex-managed block. It is scoped to the restricted `Molty` vault. - Older shells may expose the same value as `MOLTY_OP_SERVICE_ACCOUNT_TOKEN`; treat that as a fallback alias for known `Molty` vault items. -- If the token is not already exported, not applicable, or cannot read the exact known item/field required, ask the user before using the desktop-app 1Password flow below. +- If the token is not already exported, not applicable, or cannot read the exact known item/field required, use the desktop-app 1Password flow below automatically. Ask only when an actual unlock or other user interaction remains blocked. - Export/pass it only for the single command that needs it: `OP_SERVICE_ACCOUNT_TOKEN="$OP_SERVICE_ACCOUNT_TOKEN" op item get "" --vault Molty ...`. - Service-account `op` reads require an explicit vault query; omitting `--vault Molty` fails even when the token is valid. - Keep the tmux rule: every `op` command, including service-account reads, still runs inside one named tmux session. -- Do not enumerate vaults/items with service accounts by default. If the user explicitly asks to search, gives a screenshot/listing, or gives only a fuzzy item name, use the safe metadata search below before asking. +- Do not enumerate vaults/items with service accounts by default. If the user explicitly asks to search, gives a screenshot/listing, or gives only a fuzzy item name, use the safe metadata search below before desktop fallback. - Print presence/shape only, never token or secret values. ## Required Persistent Tmux Session @@ -166,7 +166,7 @@ chmod 700 /tmp/op-find-item.sh tmux -S "$SOCKET" send-keys -t "$SESSION:" -- "bash /tmp/op-find-item.sh; rm -f /tmp/op-find-item.sh" C-m ``` -After choosing a candidate, switch back to exact item/field JSON extraction and shape-only validation. Do not broaden from a restricted service-account vault to all vaults without explicit user approval. +After choosing a candidate, switch back to exact item/field JSON extraction and shape-only validation. An exact known personal item may use desktop fallback automatically; do not broadly enumerate personal vaults unless the user asked to search. ## Redacted debugging @@ -191,4 +191,5 @@ tmux -S "$SOCKET" send-keys -t "$SESSION" -- "bash /tmp/op-debug.sh; rm -f /tmp/ - Prefer `op run` / `op inject` over writing secrets to disk. - If sign-in without app integration is needed, use `op account add`. - If a command returns "account is not signed in", re-run `op signin` inside tmux and authorize in the app. +- Let the desktop 1Password unlock prompt request user interaction directly; do not add a separate chat permission round trip first. - Do not run `op` outside tmux; stop and ask if tmux is unavailable. From f4096e13bcc704c3a01d1ab0881b7db0bd7125a0 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Thu, 2 Jul 2026 03:21:18 -0700 Subject: [PATCH 023/242] fix: harden npm credential selection --- CHANGELOG.md | 3 + skills/npm/SKILL.md | 14 ++- skills/npm/scripts/npm-auth-login.mjs | 100 +++++++++++++++ skills/npm/scripts/npm-auth-login.test.mjs | 63 ++++++++++ skills/npm/scripts/publish-package.sh | 134 +++++++++++++++++++++ skills/npm/scripts/reserve-packages.sh | 85 ++++--------- 6 files changed, 336 insertions(+), 63 deletions(-) create mode 100755 skills/npm/scripts/npm-auth-login.mjs create mode 100644 skills/npm/scripts/npm-auth-login.test.mjs create mode 100755 skills/npm/scripts/publish-package.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index fa52fb8..fb6c897 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ summary: Timeline of guardrail helper changes mirrored from Sweetistics and rela # Changelog +## 2026-07-02 — npm Credential Field Safety +- Added a reusable npm publish helper that prefers canonical 1Password field IDs, rejects ambiguous duplicate labels, verifies registry publication, and shares the hardened login path with package reservation. + ## 2026-07-02 — UTF-8 Skill Validation - Made skill validation explicitly read UTF-8 so C locales accept non-ASCII skill front matter. Thanks @chaochaoweb3. diff --git a/skills/npm/SKILL.md b/skills/npm/SKILL.md index cb8590e..1a35bfc 100644 --- a/skills/npm/SKILL.md +++ b/skills/npm/SKILL.md @@ -18,12 +18,24 @@ Use for npm registry/account tasks: `npm whoami`, package availability, package - Still stop and ask if the `npmjs` item is missing, the account/vault is ambiguous, credentials are malformed, npm denies package access, or the requested package/version does not match the repo release target. - Run npm auth work inside one persistent tmux session. Reuse it on failure. - Keep npm auth in a temp npmrc; delete it after the command. -- If hand-rolling, read `npmjs` once, keep secrets in shell variables, require a six-digit `op item get npmjs --account my.1password.com --otp`, write a temp npmrc, run all npm commands with `NPM_CONFIG_USERCONFIG`, then delete the npmrc and unset variables. +- For normal package releases, run `scripts/publish-package.sh` from the package root inside that tmux session. Do not hand-roll field extraction or registry login. +- Credential selection must prefer canonical field `id`, then `purpose`, then a unique label. Reject duplicate label-only matches; `npmjs` can retain legacy fields with the same label. +- If hand-rolling is unavoidable, use `scripts/npm-auth-login.mjs` for field selection and registry login. Read `npmjs` once, require a six-digit OTP, keep auth in a temp npmrc, then delete it and unset variables. - npm 11 prompt piping is brittle; avoid `printf ... | npm login --auth-type=legacy`. - Avoid `expect` for npm login unless necessary; logs can echo prompts and are easy to get wrong. - Prefer the helper's registry API login path (`npm-profile` `loginCouch`) for automation. - If auth shape is ambiguous or `npm whoami` fails, stop and ask for the exact field label / credential fix. Do not probe more 1Password items or start another tmux session. +## Package Publishing + +From the package root, inside the same auth tmux session: + +```bash +/Users/steipete/Projects/agent-scripts/skills/npm/scripts/publish-package.sh +``` + +The helper verifies identity, refuses an existing package version, publishes with a fresh OTP, retries one expired OTP, verifies registry visibility, and cleans auth files. + ## Package Reservation Use `scripts/reserve-packages.sh` from inside the same tmux session: diff --git a/skills/npm/scripts/npm-auth-login.mjs b/skills/npm/scripts/npm-auth-login.mjs new file mode 100755 index 0000000..de26b69 --- /dev/null +++ b/skills/npm/scripts/npm-auth-login.mjs @@ -0,0 +1,100 @@ +#!/usr/bin/env node +import fs from "node:fs"; +import { execFileSync } from "node:child_process"; +import { createRequire } from "node:module"; +import { pathToFileURL } from "node:url"; + +const require = createRequire(import.meta.url); + +function valueMatches(fields, predicate) { + return fields.filter((field) => field?.value && predicate(field)); +} + +export function selectCredentialField( + fields, + { id, purpose, labels, displayName }, +) { + const byId = valueMatches(fields, (field) => field.id === id); + if (byId.length === 1) return String(byId[0].value); + if (byId.length > 1) throw new Error(`ambiguous canonical ${displayName} fields`); + + const byPurpose = valueMatches(fields, (field) => field.purpose === purpose); + if (byPurpose.length === 1) return String(byPurpose[0].value); + if (byPurpose.length > 1) throw new Error(`ambiguous ${displayName} purpose fields`); + + const acceptedLabels = new Set(labels.map((label) => label.toLowerCase())); + const byLabel = valueMatches(fields, (field) => + acceptedLabels.has(String(field.label ?? "").toLowerCase()), + ); + if (byLabel.length === 1) return String(byLabel[0].value); + if (byLabel.length > 1) throw new Error(`ambiguous ${displayName} label fields`); + throw new Error(`missing ${displayName} field`); +} + +export function extractNpmCredentials(item) { + const fields = Array.isArray(item?.fields) ? item.fields : []; + return { + username: selectCredentialField(fields, { + id: "username", + purpose: "USERNAME", + labels: ["username", "name"], + displayName: "username", + }), + password: selectCredentialField(fields, { + id: "password", + purpose: "PASSWORD", + labels: ["password"], + displayName: "password", + }), + }; +} + +function npmProfileCandidates() { + const roots = []; + try { + roots.push(execFileSync("npm", ["root", "-g"], { encoding: "utf8" }).trim()); + } catch {} + roots.push("/opt/homebrew/lib/node_modules", "/usr/local/lib/node_modules"); + return roots.flatMap((root) => [ + `${root}/npm/node_modules/npm-profile`, + `${root}/npm-profile`, + ]); +} + +function loadLoginCouch() { + for (const candidate of npmProfileCandidates()) { + try { + return require(candidate).loginCouch; + } catch {} + } + throw new Error("could not load npm-profile loginCouch from npm installation"); +} + +async function main() { + const otp = process.env.NPM_OTP ?? ""; + const npmrc = process.env.NPMRC ?? ""; + const registry = process.env.REGISTRY ?? "https://registry.npmjs.org/"; + if (!/^\d{6}$/.test(otp)) throw new Error("npm OTP must be six digits"); + if (!npmrc) throw new Error("NPMRC path is required"); + + const input = fs.readFileSync(0, "utf8"); + const { username, password } = extractNpmCredentials(JSON.parse(input)); + const result = await loadLoginCouch()(username, password, { registry, otp }); + if (!result?.token) throw new Error("registry did not return an npm token"); + + const authHost = new URL(registry).host; + fs.writeFileSync(npmrc, `//${authHost}/:_authToken=${result.token}\n`, { + mode: 0o600, + }); + console.log(`npm registry session created for ${result.username || username}`); +} + +if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) { + main().catch((error) => { + console.error(error?.code ? `${error.code}: ${error.message}` : error.message); + if (error?.body) { + console.error(String(error.body).replace(/\b\d{6}\b/g, "OTP_REDACTED")); + } + process.exit(1); + }); +} diff --git a/skills/npm/scripts/npm-auth-login.test.mjs b/skills/npm/scripts/npm-auth-login.test.mjs new file mode 100644 index 0000000..4bcacc6 --- /dev/null +++ b/skills/npm/scripts/npm-auth-login.test.mjs @@ -0,0 +1,63 @@ +import assert from "node:assert/strict"; +import test from "node:test"; +import { + extractNpmCredentials, + selectCredentialField, +} from "./npm-auth-login.mjs"; + +test("canonical IDs beat earlier duplicate labels", () => { + const credentials = extractNpmCredentials({ + fields: [ + { label: "password", type: "STRING", value: "stale-password" }, + { id: "username", label: "name", purpose: "USERNAME", value: "owner" }, + { + id: "password", + label: "password", + purpose: "PASSWORD", + type: "CONCEALED", + value: "current-password", + }, + ], + }); + + assert.deepEqual(credentials, { + username: "owner", + password: "current-password", + }); +}); + +test("purpose beats labels when canonical IDs are absent", () => { + const value = selectCredentialField( + [ + { label: "password", value: "legacy" }, + { label: "login secret", purpose: "PASSWORD", value: "current" }, + ], + { + id: "password", + purpose: "PASSWORD", + labels: ["password"], + displayName: "password", + }, + ); + + assert.equal(value, "current"); +}); + +test("duplicate label-only fields are rejected", () => { + assert.throws( + () => + selectCredentialField( + [ + { label: "password", value: "one" }, + { label: "password", value: "two" }, + ], + { + id: "password", + purpose: "PASSWORD", + labels: ["password"], + displayName: "password", + }, + ), + /ambiguous password label fields/, + ); +}); diff --git a/skills/npm/scripts/publish-package.sh b/skills/npm/scripts/publish-package.sh new file mode 100755 index 0000000..7a2c72d --- /dev/null +++ b/skills/npm/scripts/publish-package.sh @@ -0,0 +1,134 @@ +#!/usr/bin/env bash +set -euo pipefail +set +x + +usage() { + cat <<'USAGE' +Usage: + publish-package.sh [--account ACCOUNT] [--item ITEM] [--access ACCESS] [--tag TAG] + +Publishes the package in the current directory through a temporary authenticated +npmrc. Must run inside the persistent tmux session used for 1Password access. +USAGE +} + +ACCOUNT="${NPM_OP_ACCOUNT:-my.1password.com}" +ITEM="${NPM_OP_ITEM:-npmjs}" +REGISTRY="${NPM_REGISTRY:-https://registry.npmjs.org/}" +ACCESS="public" +TAG="latest" + +while [ "$#" -gt 0 ]; do + case "$1" in + --account) ACCOUNT="${2:?missing account}"; shift 2 ;; + --item) ITEM="${2:?missing item}"; shift 2 ;; + --access) ACCESS="${2:?missing access}"; shift 2 ;; + --tag) TAG="${2:?missing tag}"; shift 2 ;; + -h|--help) usage; exit 0 ;; + *) echo "unknown argument: $1" >&2; usage >&2; exit 2 ;; + esac +done + +if [ -z "${TMUX:-}" ]; then + echo "refusing to run: npm auth must stay inside one persistent tmux session" >&2 + exit 2 +fi + +for bin in op node npm; do + command -v "$bin" >/dev/null 2>&1 || { echo "missing required binary: $bin" >&2; exit 2; } +done +test -f package.json || { echo "package.json not found in current directory" >&2; exit 2; } + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +WORK="$(mktemp -d /tmp/npm-publish.XXXXXX)" +NPMRC="$WORK/npmrc" +cleanup() { + rm -rf "$WORK" + unset ITEM_JSON NPM_OTP NPMRC SA_TOKEN +} +trap cleanup EXIT + +redact() { + sed -E 's/(npm_[A-Za-z0-9_]+)/npm_REDACTED/g; s/[0-9]{6}/OTP_REDACTED/g' +} + +name="$(node -p 'require("./package.json").name')" +version="$(node -p 'require("./package.json").version')" +if npm view "$name@$version" version >/dev/null 2>&1; then + echo "$name@$version is already published" >&2 + exit 5 +fi + +SA_TOKEN="${OP_SERVICE_ACCOUNT_TOKEN:-${MOLTY_OP_SERVICE_ACCOUNT_TOKEN:-}}" +AUTH_MODE="desktop" +if [ -n "$SA_TOKEN" ] && ITEM_JSON="$(OP_SERVICE_ACCOUNT_TOKEN="$SA_TOKEN" op item get "$ITEM" --vault Molty --format json 2>/dev/null)"; then + AUTH_MODE="service" + echo "1Password access: service account" +else + unset OP_SERVICE_ACCOUNT_TOKEN MOLTY_OP_SERVICE_ACCOUNT_TOKEN SA_TOKEN + op signin --account "$ACCOUNT" >/dev/null + op whoami --account "$ACCOUNT" >/dev/null + ITEM_JSON="$(op item get "$ITEM" --account "$ACCOUNT" --format json)" + echo "1Password access: desktop" +fi + +current_otp() { + if [ "$AUTH_MODE" = "service" ]; then + OP_SERVICE_ACCOUNT_TOKEN="$SA_TOKEN" op item get "$ITEM" --vault Molty --otp 2>/dev/null | tr -d '[:space:]' + else + op item get "$ITEM" --account "$ACCOUNT" --otp 2>/dev/null | tr -d '[:space:]' + fi +} + +NPM_OTP="$(current_otp)" +case "$NPM_OTP" in + [0-9][0-9][0-9][0-9][0-9][0-9]) ;; + *) echo "$ITEM has no usable six-digit OTP field" >&2; exit 3 ;; +esac + +login_log="$WORK/npm-login.log" +printf "%s" "$ITEM_JSON" | + NPM_OTP="$NPM_OTP" NPMRC="$NPMRC" REGISTRY="$REGISTRY" \ + node "$SCRIPT_DIR/npm-auth-login.mjs" >"$login_log" 2>&1 || { + echo "npm registry login failed" >&2 + redact <"$login_log" >&2 + exit 3 + } +unset ITEM_JSON +redact <"$login_log" + +who="$(NPM_CONFIG_USERCONFIG="$NPMRC" npm whoami 2>"$WORK/npm-whoami.log" || true)" +if [ -z "$who" ]; then + echo "npm auth check failed" >&2 + redact <"$WORK/npm-whoami.log" >&2 + exit 4 +fi +echo "npm auth ok as $who" + +publish_log="$WORK/npm-publish.log" +NPM_OTP="$(current_otp)" +if ! NPM_CONFIG_USERCONFIG="$NPMRC" npm publish --access "$ACCESS" --tag "$TAG" --otp "$NPM_OTP" >"$publish_log" 2>&1; then + if grep -qiE 'otp|one-time|two-factor|2fa|EOTP' "$publish_log"; then + echo "publish OTP expired; retrying once with a fresh OTP" >&2 + NPM_OTP="$(current_otp)" + NPM_CONFIG_USERCONFIG="$NPMRC" npm publish --access "$ACCESS" --tag "$TAG" --otp "$NPM_OTP" >"$publish_log" 2>&1 || { + redact <"$publish_log" >&2 + exit 6 + } + else + redact <"$publish_log" >&2 + exit 6 + fi +fi +redact <"$publish_log" + +for _ in {1..12}; do + published="$(npm view "$name@$version" version 2>/dev/null || true)" + if [ "$published" = "$version" ]; then + echo "registry version verified: $name@$published" + exit 0 + fi + sleep 5 +done +echo "registry did not expose $name@$version in time" >&2 +exit 7 diff --git a/skills/npm/scripts/reserve-packages.sh b/skills/npm/scripts/reserve-packages.sh index 4d3e897..bc7f359 100755 --- a/skills/npm/scripts/reserve-packages.sh +++ b/skills/npm/scripts/reserve-packages.sh @@ -80,15 +80,15 @@ need_bin() { } need_bin op -need_bin jq need_bin node need_bin npm WORK="$(mktemp -d /tmp/npm-reserve.XXXXXX)" NPMRC="/tmp/npm-reserve-npmrc.$$" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cleanup() { rm -rf "$WORK" "$NPMRC" - unset NPM_USER NPM_PASS NPM_OTP NPMRC REGISTRY + unset ITEM_JSON NPM_OTP NPMRC REGISTRY SA_TOKEN } trap cleanup EXIT @@ -96,20 +96,26 @@ redact() { sed -E 's/(npm_[A-Za-z0-9_]+)/npm_REDACTED/g; s/[0-9]{6}/OTP_REDACTED/g' } -op signin --account "$ACCOUNT" >/dev/null -op whoami --account "$ACCOUNT" >/dev/null -echo "op auth ok; reading npm item once: $ITEM" -ITEM_JSON="$(op item get "$ITEM" --account "$ACCOUNT" --format json)" - -NPM_USER="$(printf "%s" "$ITEM_JSON" | jq -r '.fields[]? | select((.purpose // "") == "USERNAME" or (.id // "") == "username" or (.label // "" | ascii_downcase) == "name") | .value // ""' | head -1)" -NPM_PASS="$(printf "%s" "$ITEM_JSON" | jq -r '.fields[]? | select((.purpose // "") == "PASSWORD" or (.id // "") == "password") | .value // ""' | head -1)" -if [ -z "${NPM_USER:-}" ] || [ -z "${NPM_PASS:-}" ]; then - echo "$ITEM is missing username or password fields" >&2 - exit 2 +SA_TOKEN="${OP_SERVICE_ACCOUNT_TOKEN:-${MOLTY_OP_SERVICE_ACCOUNT_TOKEN:-}}" +AUTH_MODE="desktop" +if [ -n "$SA_TOKEN" ] && ITEM_JSON="$(OP_SERVICE_ACCOUNT_TOKEN="$SA_TOKEN" op item get "$ITEM" --vault Molty --format json 2>/dev/null)"; then + AUTH_MODE="service" + echo "1Password access: service account" +else + unset OP_SERVICE_ACCOUNT_TOKEN MOLTY_OP_SERVICE_ACCOUNT_TOKEN SA_TOKEN + op signin --account "$ACCOUNT" >/dev/null + op whoami --account "$ACCOUNT" >/dev/null + ITEM_JSON="$(op item get "$ITEM" --account "$ACCOUNT" --format json)" + echo "1Password access: desktop" fi +echo "op auth ok; reading npm item once: $ITEM" current_otp() { - op item get "$ITEM" --account "$ACCOUNT" --otp 2>/dev/null | tr -d '[:space:]' || true + if [ "$AUTH_MODE" = "service" ]; then + OP_SERVICE_ACCOUNT_TOKEN="$SA_TOKEN" op item get "$ITEM" --vault Molty --otp 2>/dev/null | tr -d '[:space:]' || true + else + op item get "$ITEM" --account "$ACCOUNT" --otp 2>/dev/null | tr -d '[:space:]' || true + fi } NPM_OTP="$(current_otp)" @@ -125,60 +131,15 @@ case "$NPM_OTP" in ;; esac -export NPM_USER NPM_PASS NPM_OTP NPMRC REGISTRY login_log="$WORK/npm-login.log" -node >"$login_log" 2>&1 <<'NODE' || { -const fs = require('node:fs') -const { execFileSync } = require('node:child_process') - -function candidates () { - const roots = [] - try { - roots.push(execFileSync('npm', ['root', '-g'], { encoding: 'utf8' }).trim()) - } catch {} - roots.push('/opt/homebrew/lib/node_modules', '/usr/local/lib/node_modules') - return roots.flatMap(root => [ - `${root}/npm/node_modules/npm-profile`, - `${root}/npm-profile`, - ]) -} - -let loginCouch -for (const candidate of candidates()) { - try { - loginCouch = require(candidate).loginCouch - break - } catch {} -} -if (!loginCouch) { - throw new Error('could not load npm-profile loginCouch from npm installation') -} - -async function main () { - const res = await loginCouch(process.env.NPM_USER, process.env.NPM_PASS, { - registry: process.env.REGISTRY, - otp: process.env.NPM_OTP, - }) - if (!res || !res.token) { - throw new Error('registry did not return an npm token') - } - const authHost = new URL(process.env.REGISTRY).host - fs.writeFileSync(process.env.NPMRC, `//${authHost}/:_authToken=${res.token}\n`, { mode: 0o600 }) - console.log(`npm registry session created for ${res.username || process.env.NPM_USER}`) -} - -main().catch(err => { - console.error(err && err.code ? `${err.code}: ${err.message}` : err) - if (err && err.body) { - console.error(String(err.body).replace(/[0-9]{6}/g, 'OTP_REDACTED')) - } - process.exit(1) -}) -NODE +printf "%s" "$ITEM_JSON" | + NPM_OTP="$NPM_OTP" NPMRC="$NPMRC" REGISTRY="$REGISTRY" \ + node "$SCRIPT_DIR/npm-auth-login.mjs" >"$login_log" 2>&1 || { echo "npm registry login failed" >&2 redact <"$login_log" >&2 exit 3 } +unset ITEM_JSON redact <"$login_log" who="$(NPM_CONFIG_USERCONFIG="$NPMRC" npm whoami 2>"$WORK/npm-whoami.log" || true)" From 590e75daa12d2dd0f15f6bacfffab583a35887fc Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 3 Jul 2026 20:19:46 -0700 Subject: [PATCH 024/242] feat: add sync-skills claude/codex skill mirror script --- CHANGELOG.md | 3 ++ README.md | 13 ++++-- scripts/sync-skills | 103 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 115 insertions(+), 4 deletions(-) create mode 100755 scripts/sync-skills diff --git a/CHANGELOG.md b/CHANGELOG.md index fb6c897..ca72000 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ summary: Timeline of guardrail helper changes mirrored from Sweetistics and rela # Changelog +## 2026-07-03 — Claude Skill Mirror +- Added `scripts/sync-skills`: builds the per-machine skill mirror (Codex whole-root links, flat per-skill Claude links with agent-scripts > manager > codex-local priority, shared `AGENTS.MD` pointers) since Claude Code only scans `~/.claude/skills` one level deep; documented the layout in the README. + ## 2026-07-02 — npm Credential Field Safety - Added a reusable npm publish helper that prefers canonical 1Password field IDs, rejects ambiguous duplicate labels, verifies registry publication, and shares the hardened login path with package reservation. diff --git a/README.md b/README.md index 4eeccad..dce7481 100644 --- a/README.md +++ b/README.md @@ -26,9 +26,10 @@ Rules: - Validate after edits: `scripts/validate-skills`. - Quote `description` in front matter. -Global discovery usually points here: -- `~/.codex/skills -> ~/Projects/agent-scripts/skills` -- `~/.claude/skills -> ~/Projects/agent-scripts/skills` +Global discovery is built by `scripts/sync-skills` (idempotent; run on every Mac after cloning or adding skills): +- Codex scans nested dirs, so it gets whole-root links: `~/.codex/skills/agent-scripts -> ~/Projects/agent-scripts/skills`, `~/.codex/skills/manager -> ~/Projects/manager/skills`. +- Claude Code loads only `~/.claude/skills//SKILL.md` (exactly one level deep; per-entry symlinks are followed, category subfolders are not scanned — verified on 2.1.197). It gets a flat per-skill link mirror covering both repos plus machine-local `~/.codex/skills/` extras. +- Name collisions resolve agent-scripts > manager > codex-local; the script prints skipped duplicates and prunes broken/stale managed links. Shared personal skills live as real folders in `skills/`. Public OpenClaw shared skills live in `../agent-skills` and are exposed here with tracked relative symlinks. Repo-owned skills stay canonical in their repo and are exposed here the same way, for example: @@ -43,7 +44,7 @@ Current symlinked repo-owned skills include `birdclaw`, `discrawl`, `gog`, `imsg Shared hard rules live in `AGENTS.MD`. -Global setup: +Global setup (also maintained by `scripts/sync-skills`; Claude Code reads `CLAUDE.md` only, so it links to the shared `AGENTS.MD`): - `~/.codex/AGENTS.md -> ~/Projects/agent-scripts/AGENTS.MD` - `~/.claude/CLAUDE.md -> ~/Projects/agent-scripts/AGENTS.MD` - `~/.claude/AGENTS.md -> ~/Projects/agent-scripts/AGENTS.MD` @@ -63,6 +64,10 @@ Repo-specific rules go below that pointer. Do not copy the shared blocks into do - Enforces a non-empty commit message. - Runs skill validation before committing. +`scripts/sync-skills` +- Builds the per-machine skill mirror: Codex whole-root links, Claude flat per-skill links, shared `AGENTS.MD` pointers. +- Idempotent; prints changes only, prunes broken/stale managed links, never clobbers real files. + `scripts/validate-skills` - Checks every `skills/*/SKILL.md`. - Verifies YAML front matter plus required `name` and `description`. diff --git a/scripts/sync-skills b/scripts/sync-skills new file mode 100755 index 0000000..cc4bdd4 --- /dev/null +++ b/scripts/sync-skills @@ -0,0 +1,103 @@ +#!/usr/bin/env bash +# sync-skills: build/refresh the per-machine agent skill mirror. Idempotent. +# +# Codex scans ~/.codex/skills recursively, so it gets whole-root symlinks. +# Claude Code loads only ~/.claude/skills//SKILL.md (one level deep, +# per-entry symlinks followed, no recursive scan; verified live on 2.1.197), +# so it gets a flat per-skill symlink mirror instead. +# Collision priority: agent-scripts > manager > codex-local extras. +set -eo pipefail + +AGENT_SKILLS="$HOME/Projects/agent-scripts/skills" +MANAGER_SKILLS="$HOME/Projects/manager/skills" +CODEX_ROOT="$HOME/.codex/skills" +CLAUDE_ROOT="$HOME/.claude/skills" +AGENTS_MD="$HOME/Projects/agent-scripts/AGENTS.MD" + +changed=0 +note() { printf '%s\n' "$*"; changed=1; } + +# link : create/retarget symlink, quiet when already right. +link() { + [ "$(readlink "$2" 2>/dev/null)" = "$1" ] && return 0 + ln -sfn "$1" "$2" + note "link $2 -> $1" +} + +# --- Claude root must be a real dir; the old layout symlinked the whole dir, +# which hid manager + codex-local skills. +if [ -L "$CLAUDE_ROOT" ]; then + rm "$CLAUDE_ROOT" + note "replaced legacy whole-dir symlink $CLAUDE_ROOT with real dir" +fi +mkdir -p "$CLAUDE_ROOT" "$CODEX_ROOT" + +# --- Codex: whole-root links. +[ -d "$AGENT_SKILLS" ] && link "$AGENT_SKILLS" "$CODEX_ROOT/agent-scripts" +[ -d "$MANAGER_SKILLS" ] && link "$MANAGER_SKILLS" "$CODEX_ROOT/manager" + +# --- Claude: collect desired name -> target (bash 3.2: parallel arrays). +names=() +targets=() +lookup() { + local i + for i in "${!names[@]}"; do + [ "${names[$i]}" = "$1" ] && { printf '%s' "${targets[$i]}"; return 0; } + done + return 1 +} +claim() { # claim