Addresses items 4, 5, 7 from the self-review of the batch merge. PR A
(#228) covered items 1, 2, 3, 6 on the Go side.
## workspace-template/main.py — idle loop hardening
- Replace asyncio.get_event_loop() with asyncio.get_running_loop() —
the former is deprecated in 3.12+ and emits a DeprecationWarning on
every idle fire.
- Replace hardcoded urlopen timeout=600 with IDLE_FIRE_TIMEOUT_SECONDS
clamped to max(60, min(300, idle_interval_seconds)). Long cadence
workspaces no longer hold dangling requests open for 10 minutes; the
cap adapts automatically when the interval is short.
- Type the exception handling: split HTTPError (has .code) from URLError
(connection-level) from the generic catch-all. Log status + error
class separately so operators can grep for specific failure modes
instead of a bare "post failed".
- Fire-and-forget no longer loses exceptions. run_in_executor Future
now has an add_done_callback that logs the outcome, so a panic in
_post_sync surfaces as "Idle loop: post failed — status=None err=..."
instead of Python's default "Task exception was never retrieved"
warning burried in stderr.
## org-templates/molecule-dev/org.yaml — discoverability
Added idle_prompt + idle_interval_seconds to the defaults: block with
explanatory comments. Without this, users had to read main.py to
discover the feature.
## docs/runbooks/admin-auth.md — new
Documents the three middleware variants (AdminAuth strict,
CanvasOrBearer soft, WorkspaceAuth per-id), the exact contract of each,
and the three-question test for adding a new route to CanvasOrBearer.
Also flags the session-cookie follow-up as Phase H.
Referenced PRs: #138, #164, #165, #166, #167, #168, #190, #194, #203,
#228.
No code deltas in platform/ beyond the Python + YAML + docs changes.
Full pytest suite unchanged except the pre-existing test_hermes_smoke
flake that fails in full-suite but passes in isolation (test isolation
bug, not introduced by this PR).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Every agent in the reno-stars org (marketing, sales, dev, coordinator)
plausibly needs browser access at some point — social posts, GBP edits,
directory submissions, InvoiceSimple publish. Without the plugin on
first import, agents fall back to launching their own Chromium inside
the container, which doesn't have the operator's authenticated Chrome
profile (no logged-in sessions, no saved cookies).
Per-agent opt-out via `!browser-automation` is already supported
(PR #71 UNION merge semantics) if any specific role shouldn't have it.
Closes#213
Every-10-min cadence introduced in PR #159 increased Security Auditor
from 2 runs/day to 144 runs/day (144x). Combined with PM, Research Lead,
Dev Lead, and other hourly evolution-lever crons, this is the likely
root cause of the P0 OAuth quota exhaustion (#160, resets Apr 17 23:00 UTC).
Restored: cron_expr 7 6,18 * * * (twice daily, 12-hour interval)
Schedule name updated to match new cadence.
Audit prompt content (DAST teardown, PM routing, PM deliverable) retained.
Supersedes #158 (10-min uniform bump). That PR was too blunt — it treated
research/audit/orchestration crons the same when they have fundamentally
different cost/value/cadence profiles.
## The split
Three layers, three cadences, grounded in the survey of Hermes/Letta/
Trigger.dev/Inngest/AG2/Rivet/n8n/Composio/SWE-agent done this session.
Nobody in that survey runs while(true) per agent — they all combine
event-driven reactivity with short orchestration pulses on a coordinator.
This PR implements that split for our 12-workspace template.
| Layer | Roles | Cadence | Purpose |
|---|---|---|---|
| Orchestration | PM, Dev Lead, Research Lead | every 5 min | Check backlog, dispatch work, review completed tasks |
| Audit | Security Auditor | every 10 min | Focused security audit |
| Audit | UI/UX Designer | every 15 min | Vision-heavy, dial back from 10 |
| Deep-work | Research Lead (eco-watch) | every 30 min (8,38) | Was hourly |
| Deep-work | Dev Lead (template fitness) | every 30 min (15,45) | Was hourly |
| Deep-work | Technical Researcher (plugins) | hourly (unchanged) | Research-heavy, slow |
| Deep-work | DevOps (channels) | hourly (unchanged) | Research-heavy, slow |
| Reactive | BE, FE, DevOps, Docs | no cron | Execute A2A delegations |
## Orchestration pulse prompts
The three new schedules each carry a detailed orchestration_prompt:
- **PM** (5-min): scan all 12 workspaces, scan GH PRs/issues backlog
(external), scan memory backlog (internal), dispatch up to 3 tasks per
pulse, review completed work, write pulse summary to memory. Hard
rules: under 90s wall-clock, never dispatch to busy agents, write
"orchestrator-clean" and stop if genuinely nothing to do.
- **Dev Lead** (5-min, offset +1 from PM): same shape, scoped to
engineering team. Reviews open PRs from direct reports, matches idle
engineers to labeled GH issues (security/bug/feature), dispatches with
"fix/issue-N-slug" branch convention. Skips pulse if own template
fitness audit is in flight (:15, :45).
- **Research Lead** (5-min, offset +2 from PM): same shape, scoped to
research team. Matches Market Analyst / Technical Researcher /
Competitive Intelligence to research-labeled issues or memory-stashed
questions. Max 2 A2A per pulse (research is slow). Skips pulse if own
eco-watch is in flight (:8, :38).
## Cadence offset table
No two crons fire in the same minute:
:01,:11,:21,:31,:41,:51 — Security audit (Security Auditor)
:02,:07,:12,:17,:22,:27,:32,:37,:42,:47,:52,:57 — Dev Lead orchestrator
:04,:09,:14,:19,:24,:29,:34,:39,:44,:49,:54,:59 — Research Lead orchestrator
:01,:06,:11,:16,:21,:26,:31,:36,:41,:46,:51,:56 — PM orchestrator
:05,:20,:35,:50 — UI/UX audit (UIUX Designer)
:08,:38 — Ecosystem watch deep-work (Research Lead)
:15,:45 — Template fitness deep-work (Dev Lead)
:22 — Plugin curation (Technical Researcher)
:47 — Channel expansion (DevOps Engineer)
Note PM and Security Auditor share :01 — this is fine because they
target different workspaces so scheduler concurrency handles it.
## Cost estimate
- PM pulse: 12/hour × 24 × ~3k tokens = 864k tokens/day/org ~ $5/day
- Dev Lead pulse: same ~ $5/day
- Research Lead pulse: same ~ $5/day
- Audits (security 10min, UIUX 15min): ~$8/day/org combined
- Deep-work crons (unchanged from original): ~$4/day/org
**Total ~$27/day/org**. Comparable to #158's $25 but MUCH higher
utility because orchestration produces dispatches that keep workers
busy, whereas #158 just fired more audits against the same team.
Closes#158 (superseded — will close that PR with a pointer to this one).
## Related research
See docs/ecosystem-watch.md `### Hermes Agent` and today's research agent
output: event-driven + reflection-on-completion + short orchestration
pulses on leaders is the shape that delivers 24/7 activity without
runaway cost. This is the concrete implementation.
Closes#133. Both roles previously inherited defaults only (ecc,
molecule-dev, superpowers, careful-bash, prompt-watchdog, audit-trail,
session-context, cron-learnings, update-docs) — no review skill.
Dev Lead enforces PR quality gates per triage SKILL.md; QA Engineer
reviews test coverage against acceptance criteria. Both need the
16-criteria code-review rubric and llm-judge to operate deterministically.
Mirrors Security Auditor's existing \`[molecule-skill-code-review,
molecule-skill-cross-vendor-review, molecule-skill-llm-judge]\` override.
Dropped cross-vendor from these two since it's a noteworthy-PR tool —
the workflow-triage entry in defaults already gates that for the ticks
that need it.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Closes#93 and #105.
#93 — add research/plugins/template/channels entries to org.yaml
category_routing defaults. Without them, evolution crons firing with
these categories found no target and their audit summaries silently
dropped at PM. Routes each back to the role that generated it so the
author acts on their own findings.
#105 — emit X-RateLimit-Limit / -Remaining / -Reset on every response
(allowed and throttled) and Retry-After on 429s per RFC 6585. 2 tests
cover both paths. Clients and monitoring tools can now back off
proactively instead of polling into 429 walls.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CEO 2026-04-15: the team's evolution loops should be hourly, not daily/weekly.
A 24h or 7d cadence is the wrong rhythm for a team that's expected to run 24/7
and keep improving. At hourly, every drift, every new project, every plugin
gap, every channel opportunity gets surfaced within an hour of becoming visible.
| Schedule | Was | Now |
|-----------------------------------|----------------|--------------|
| Hourly ecosystem watch | 0 8 * * * | 8 * * * * |
| Hourly plugin curation | 0 9 * * 1 | 22 * * * * |
| Hourly template fitness audit | 30 8 * * * | 15 * * * * |
| Hourly channel expansion survey | 0 10 * * 1 | 47 * * * * |
Spread across the hour (:08, :11, :15, :17, :22, :47) so the four evolution
crons + UIUX :11 + Security :17 don't collide and don't all bury PM with
audit_summary deliveries at the same instant.
Renamed from "Daily..." / "Weekly..." to "Hourly..." to match the new cadence
and so the prompts (which still say "Daily survey" etc.) read consistently.
A follow-up will fix the body wording.
Live-synced into running DB via PATCH (3 of 4) and direct UPDATE on the 4th
(Dev Lead workspace requires a token the script didn't have). next_run_at
recomputed for all 4. First fire: 04:47 UTC (channel expansion).
Per CEO 2026-04-15: the SaaS controlplane (Molecule-AI/molecule-controlplane,
PRIVATE Go/Fly.io provisioner) needs documentation coverage too.
Updates the agent's role description, initial_prompt, and daily docs-sync
cron to handle a third repo with a strict public/private split.
## Privacy rule (the critical addition)
molecule-controlplane is private. Two-bucket model:
Internal-only changes (handlers, schemas, infra config, billing logic,
fly.toml, provisioner internals) → docs go INSIDE the controlplane repo
itself (README.md, PLAN.md, docs/internal/*.md). NEVER mentioned in the
public docs site.
Customer-facing changes (new tier, new region, new SLA, pricing change,
signup flow change) → sanitized PUBLIC description on doc.moleculesai.app.
Describes the PRODUCT, never the implementation.
When unsure: default to internal-only and ask PM before publishing.
The privacy rule is repeated three times in the prompt (top of initial_prompt,
1b inside the daily cron, and the role description) so the agent can't miss it.
## Changes
- role: extended to mention all three repos + privacy split
- initial_prompt: clones controlplane in step 1, reads README+PLAN in step 5,
scans recent commits in step 8, lists the four owned surfaces with public/private
labels in step 10
- Daily cron: adds step 1b "PAIR RECENT CONTROLPLANE PRS" with the (i)/(ii)
internal/customer-facing branching logic
- SETUP block: adds controlplane git pull
Adds a 13th workspace to the molecule-dev template owning end-to-end
documentation across all Molecule AI surfaces.
## Why now
- We just created Molecule-AI/docs (customer-facing site at
doc.moleculesai.app, Fumadocs + Next.js 15) and the customer site needs
someone to own it.
- Internal docs (README.md, docs/architecture.md, docs/edit-history/) were
drifting — every platform PR has been opening a docs sync PR manually.
- No agent in the team owned terminology consistency or stub backfill.
## Where it sits in the org
Third PM direct report, parallel to Research Lead and Dev Lead — docs is
its own swim lane that spans engineering (docs follow code) and
research/product (concepts and terminology).
PM
├── Research Lead
├── Dev Lead
└── Documentation Specialist <-- new
## Schedules (2)
1. **Daily docs sync — backfill stubs and pair recent platform PRs**
`0 9 * * *` — every morning:
- Pair every merged platform PR (last 24h) with a docs PR if needed
- Backfill one stub page on the docs site
- Crawl the live site for broken links / dead anchors
- delegate_task to PM with audit_summary (category=docs)
2. **Weekly terminology + freshness audit**
`0 11 * * 1` — every Monday:
- Stale page detection (>30 days untouched on fast-moving surfaces)
- Terminology consistency check (one canonical name per concept)
- Link-rot scan
- Same audit_summary contract
## Plugins
Inherits the 9 universal defaults. Adds `browser-automation` for crawling
the live docs site. `molecule-skill-update-docs` is already in defaults
so the cross-repo sync skill is available.
## Routing
Adds `docs: [Documentation Specialist]` to `category_routing` so any
agent that emits an audit_summary with category=docs is auto-routed
here by the platform.
## Bind mounts
Note: this workspace clones BOTH /workspace/repo (the platform monorepo)
and /workspace/docs (Molecule-AI/docs) in its initial_prompt so the
agent can edit either side.
Today's crons are all REVIEW (Security audit, UIUX audit, QA tests). Nothing
actively pushes the team to EVOLVE the four levers CEO named: templates,
plugins, channels, watchlist. The team-runs-24/7 goal needs both — defensive
reviews AND offensive evolution.
Adds 4 new schedules:
1. Research Lead — Daily ecosystem watch (0 8 * * *)
Survey github.com/trending + HN + AI-blogs for new agent-infra projects
from the last 24h. Add 1-3 entries to docs/ecosystem-watch.md per day,
commit to chore/eco-watch-YYYY-MM-DD branch + push + PR. Re-enables
the watchlist pipeline that was paused earlier today.
2. Technical Researcher — Weekly plugin curation (0 9 * * 1, Mondays)
Inventory plugins/ + builtin_tools/ + recent landings. Identify gaps
(builtin not exposed as plugin; role missing extras; rarely-used plugin
in defaults). Survey upstream (claude.ai cookbook, MCP servers,
anthropic/openai/langchain blogs). File 1-3 plugin proposals per week
as GH issues with concrete integration sketches.
3. Dev Lead — Daily template fitness audit (30 8 * * *)
Health-check the template itself: stale system prompts, schedules not
firing (catches the #85 scheduler-died failure mode), roles missing
plugins they should have, missing crons, channel gaps. File issues for
any drift. Designed to catch the silent-stall pattern from today's
incident.
4. DevOps Engineer — Weekly channel expansion survey (0 10 * * 1, Mondays)
PM is the only role with a channel today (Telegram). Survey what
channel infra the platform supports + what role-channel pairings would
actually help (Security→email-on-critical, DevOps→Slack-on-CI-break,
etc). File channel-proposal issues.
All four crons end with the structured audit_summary routing per #51/#75
(category, severity, issues, top_recommendation) so they integrate with
the platform-level category_routing PM uses to fan out work. The template's
existing category_routing block already maps research / plugins / template /
channels — these new crons consume exactly those slots.
Also drops three stale "# UNION with defaults (#71)" comments left from
the cleanup PR — those plugins lists are now self-documenting after #71.
Aligns with north-star goal: team should run 24/7 AND keep getting better
across templates / plugins / channels / watchlist. This PR closes the gap
where the "review" half of the loop was running but the "evolve" half had
no active driver.
Add a category_routing block to org.yaml schema (defaults + per-workspace,
UNION semantics with per-key replace). The merged routing table is rendered
into each workspace's config.yaml at import time.
PM's system prompt loses the hardcoded security/ui/infra → role mapping
from PR #50; instead it reads category_routing from /configs/config.yaml
and delegates to whatever roles the org template lists for the incoming
audit-summary's category. Future org templates ship their own routing
without prompt churn.
Tests: 4 new TestCategoryRouting_* cases covering YAML parse, UNION+drop
semantics, deterministic config.yaml render, and empty-map handling.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
#71 just merged — per-workspace `plugins:` now UNIONs with `defaults.plugins`
instead of replacing it. Simplifies every override in molecule-dev/ from
"defaults+1 = list 10 items" to "defaults+1 = list 1 item":
PM: 11 items → 2 (workflow-triage + workflow-retro)
Research Lead: 10 items → 1 (browser-automation)
Market Analyst: 10 items → 1
Technical Researcher: 10 items → 1
Competitive Intel: 10 items → 1
Security Auditor: 12 items → 3 (code-review + cross-vendor-review + llm-judge)
UIUX Designer: 10 items → 1 (browser-automation)
Every workspace still receives the full 9-plugin default set (ecc,
molecule-dev, superpowers, careful-bash, prompt-watchdog, audit-trail,
session-context, cron-learnings, update-docs) — verified by reading
mergePlugins() in platform/internal/handlers/org.go:645.
Also drops the stale "REPLACE not UNION" warning comments and points
defaults' header comment at the new union behaviour.
Net diff: ~30 lines removed, ~10 added. Template is now meaningfully
easier to extend — each new defaults.plugin propagates everywhere
without sweeping per-role lists.
Closes follow-up scope from PR #70.
PR #63 just merged 12 new modular plugins (split from a single guardrails
bundle) and the audit pipeline (Security/UIUX/QA crons) is now producing
PRs continuously. Time to wire the new plugins into the molecule-dev
template so every workspace + every cron tick benefits.
## Defaults — universal additions (was 3, now 9)
- molecule-careful-bash — refuse rm -rf, push --force main, DROP TABLE
- molecule-prompt-watchdog — warn on destructive user prompts
- molecule-audit-trail — append every Edit/Write to .claude/audit.jsonl
- molecule-session-context — auto-load cron learnings + PR/issue counts on SessionStart
- molecule-skill-cron-learnings — per-tick learning JSONL format (pairs with session-context)
- molecule-skill-update-docs — keep architecture/README/edit-history aligned
Kept: ecc, molecule-dev, superpowers.
## Per-role overrides
- PM: defaults + molecule-workflow-triage + molecule-workflow-retro
(the /triage and /retro slash commands match PM's coordination role)
- Security Auditor: defaults + molecule-skill-code-review +
molecule-skill-cross-vendor-review + molecule-skill-llm-judge
(security PRs benefit from multi-criteria review, adversarial cross-vendor
second opinion, and an LLM-judge gate that catches "agent shipped the
wrong thing")
- Research Lead + 3 researchers + UIUX Designer: defaults + browser-automation
(existing override; just synced to the new default set)
Other 5 dev roles (Dev Lead, BE, FE, DevOps, QA) inherit defaults — the
new universal set is rich enough for them; code-review skill is a runtime
opt-in if Dev Lead decides per-PR.
## REPLACE-semantics verbosity
`platform/internal/handlers/org.go:~345` treats per-workspace plugins as
REPLACE not UNION. Every override has to re-list the 9 defaults to add 1
extra. Tracked as #68 with a union-proposal; once that lands the per-role
lists shrink to just the additions.
## Test plan
- [x] YAML valid (`python -c "import yaml; yaml.safe_load(...)"`)
- [x] defaults.plugins count = 9
- [ ] After merge + re-import: every workspace's /configs/plugins/ contains
the full set; PM has /triage and /retro commands; Security Auditor
can invoke cross-vendor-review on its findings.
UIUX Designer figured out at runtime (Run 6, 2026-04-14) how to get
Playwright working without a Dockerfile change:
LD_LIBRARY_PATH="/home/agent/.cache/ms-playwright/firefox-1509/firefox"
node script.cjs
Using @sparticuz/chromium + puppeteer-core, and borrowing the NSS/NSPR
libs bundled with Playwright's Firefox binary. This resolves every missing
lib on the container without needing apt-get or image rebuild.
Agent memory persists the trick across restarts, but a fresh org-template
import (new user) would have to rediscover it. Baking the recipe into the
cron prompt so every clone inherits day-one screenshot capability.
Evidence it works (from Run 6 memory):
- 14 screenshots captured and vision-analysed
- Found 2 new criticals (C4 onboarding-guide a11y, C5 settings panel white
refresh button confirmed in production) that only surface via live DOM
- Full user-flow coverage: home → create → settings → help → templates →
mobile 375 → responsive 1280
Replaces the previous "best-effort + fall back to HTML" wording with a
specific, proven command path. Falls back on HTML only if the browser
genuinely won't launch (e.g. host.docker.internal:3000 down).
Template-level fix; the general platform-level path would be to ship
these libs in the workspace-template image directly (future Dockerfile
change — out of scope here).
Observed 2026-04-14 morning: audit crons (Security, UIUX, QA) were flowing
messages into PM per the PR #26 contract, but PM stopped sub-delegating to
Dev Lead ~10 hours ago. Meanwhile audits started opening PRs directly
(bypassing Dev Lead), and Dev Lead / BE / FE / DevOps / QA sat idle for
17+ maintenance cycles despite PRs continuing to land.
Root cause: PM's system prompt defined delegation behavior for "tasks from
CEO" but didn't explicitly treat audit summaries as tasks. PM was reading
"audit of SHA X, filed issue #N, top recommendation: fix Y" as a status
report and committing it to memory without triggering the dispatch chain.
Adds a dedicated "Audit Routing" section to PM's prompt that:
- Treats every audit summary with open issue numbers as a dispatch trigger
- Specifies routing by category (security→BE, ui→FE, infra→DevOps, qa→QA)
- Requires parallel `delegate_task_async` when issues span categories
- Makes clean-cycle acks the only no-op case
This turns PM from a receptionist into a dispatcher — which was the
original intent of the audit-routing contract in #26.
Aligns with the north-star goal (keep the team running 24/7): dead idle
windows when audits had live issue numbers is a defect in orchestration,
not a quiet period.
Follow-up to root-cause analysis in #17 (see 2026-04-14 02:14 UTC comment).
The Security Auditor's hourly DAST was creating test workspaces, secrets,
and plugins to probe auth/validation logic — but only secrets and plugins
had teardown in the prompt. Workspace-create probes leaked rows into
`workspaces` with sequential IDs aaaaaaaa- bbbbbbbb- cccccccc- dddddddd-,
each trapped in a restart loop on missing config.yaml. Four hourly runs,
four leaked workspaces.
Adds explicit step 4a: DAST TEARDOWN. Maintains three lists (workspaces,
secrets, plugins) populated as probes run, and iterates them at the end
with DELETE calls. Uses `|| true` so partial teardown failures don't
break the audit, but every created artifact gets a cleanup attempt.
Doesn't remove the cleanup the cron was already doing for secrets/plugins
— just formalises the pattern so workspace-create (and any future probe
surface) is covered by the same contract.
Related:
- #17 — rogue workspace restart loop (root cause was this)
- #26 — audit cron routing (this PR sits alongside that structure)
Currently no workspace in the molecule-dev template installs any of the
four available plugins (browser-automation, ecc, molecule-dev, superpowers).
Agents run without coding guardrails, codebase conventions, or debugging
discipline unless a plugin is installed per-workspace via the runtime
POST /workspaces/:id/plugins endpoint — which isn't happening.
Changes:
1. defaults.plugins: [ecc, molecule-dev, superpowers]
- ecc: "Everything Claude Code" — coding standards, API design,
deep research, security review, TDD workflow, node guardrails
- molecule-dev: project-specific conventions, past bugs, review-loop skill
- superpowers: systematic debugging, TDD, plan writing/execution,
verification-before-completion
All three target runtime claude_code (matches our default).
2. plugins override on Research Lead + its 3 children + UIUX Designer:
[ecc, molecule-dev, superpowers, browser-automation]
- Research agents need live web access for scraping/trending/docs,
which is core to their role.
- UIUX Designer gets Puppeteer via CDP; this may work around the
libglib/X11 gap that breaks Playwright today (#23 — the image-level
fix remains the right long-term solution, but browser-automation
uses puppeteer-core + a Chrome CDP proxy and may bypass the deps
issue entirely).
Note: platform/internal/handlers/org.go:345 treats per-workspace
`plugins:` as a REPLACEMENT of defaults (not a union), which is why
each opt-in workspace re-lists the full set. Documented inline in the
template so future editors don't accidentally drop defaults.
No other roles take browser-automation — Dev Lead, BE, FE, DevOps,
Security, QA, PM all get the default set only. If they need web access
they can install ad-hoc via the runtime plugin API.
Addresses the gap surfaced by CEO 2026-04-13: audit agents (Security
Auditor, QA Engineer, UIUX Designer) were running their crons successfully
but findings stayed in agent memory and didn't consistently flow to
GitHub issues or to developers with build ability. BE noticed Security
findings once via a manual escalation; subsequent hourly audits
accumulated 13 criticals (including an unauthenticated-plugin-install
RCE) with no durable tracking.
Changes:
1. Security Auditor schedule: replace 12h (7 6,18 * * *) with hourly
(17 * * * *) to match what's actually running in the platform DB.
Rewrite the prompt with the full body of the runtime cron — git diff
scoping, gosec/bandit, manual checklist, live API DAST, secrets scan,
open-PR review.
2. QA Engineer schedule: keep 12h cadence, tighten post-audit routing.
3. UIUX Designer: add a schedule (was previously runtime-only — see #24).
Uses hourly cadence to match runtime. Accepts Playwright may be
unavailable (see #23) and falls back to HTML analysis with the
limitation noted in the deliverable.
All three audit crons now end with an identical FINAL STEP — DELIVERABLE
ROUTING block that makes the post-audit flow MANDATORY:
a. File a GitHub issue for each CRITICAL / HIGH finding (dedupe first)
b. delegate_task to PM with a structured summary listing issue numbers;
PM decides which dev agent picks up which issue
c. Even on clean cycles, send PM a one-line "clean on SHA X" so audits
are observable
d. Memory write becomes a secondary record, not the primary deliverable
Rationale: findings need to flow into the issue tracker (durable, visible
to CEO, part of the PR/issue review feedback loop already in place) and
through PM (who owns cross-team orchestration). Memory-only output is
invisible to everyone except the auditor itself.
Related:
- #23 — UIUX Designer container missing libglib/X11 for Playwright.
This PR accepts the current limitation; #23 tracks the image fix.
- #24 — template-vs-runtime schedule drift. This PR backfills the template;
#24 tracks the platform-layer fix for preventing future drift.
- 13 open criticals in Security Auditor memory are out of scope for this
PR (that's team work once the routing is in place).
Addresses FLAG 1 and FLAG 2 from the 7-Gate review on PR #20.
FLAG 1 (token persisted on disk):
Previous: `git clone https://x-access-token:${GITHUB_TOKEN}@github.com/...` wrote
the full tokenized URL into /workspace/repo/.git/config as `[remote "origin"] url = …`.
Token survived container restarts on any bind-mounted workspace_dir.
Fix: after clone, `git remote set-url origin https://github.com/${GITHUB_REPO}.git`
scrubs the token from the remote URL. Token is only in the clone command's argv
(transient) and not persisted on disk. Falls back to anonymous for public repos.
FLAG 2 (docs not updated):
Added GITHUB_REPO and GITHUB_TOKEN entries under a new 'GitHub' section in
.env.example with notes about (a) what they're read for, (b) that GITHUB_TOKEN
should be registered as a global secret via POST /admin/secrets, (c) how it's
handled to avoid on-disk persistence.
FLAG 3 (per-workspace gating) is deferred to a separate issue — it's a platform
design question about secret scope/ACLs, not a template fix.
Fixes the template-layer half of #13. Previously initial_prompt cloned
`https://github.com/${GITHUB_REPO}.git` with no authentication, which
fails for private repos in non-TTY docker exec with:
fatal: could not read Username for 'https://github.com':
terminal prompts disabled
Now the prompt uses `https://x-access-token:${GITHUB_TOKEN}@github.com/...`
when GITHUB_TOKEN is present in env (global secret, set per CEO on 2026-04-13),
falls back to anonymous clone when it isn't.
This is a belt-and-suspenders template default. The platform-level fix
(#13) is still needed so the provisioner rewrites clone URLs
consistently, but the template should work out of the box too.