Part 2 of 4 in the org.yaml scalability refactor. Follows PR #389 which
added platform support; this PR completes the migration for every role
in the `molecule-dev` template.
## Scope
All 20 remaining roles moved from inline YAML literals to sibling .md
files under their existing `files_dir`:
- PM, Research Lead, Dev Lead, Marketing Lead (4 leaders)
- Market Analyst, Technical Researcher, Competitive Intelligence (research)
- Frontend/Backend/DevOps Engineer, Security Auditor, QA Engineer, UIUX
Designer, Triage Operator (dev team)
- DevRel, PMM, Content Marketer, Community Manager, SEO Growth Analyst,
Social Media Brand (marketing team)
Per workspace, externalized (where present):
- `initial_prompt: |...` → `initial-prompt.md` + `initial_prompt_file:`
- `idle_prompt: |...` → `idle-prompt.md` + `idle_prompt_file:`
- `schedules[*].prompt: |...` → `schedules/<slug>.md` + `prompt_file:`
Totals: 17 initial-prompt files, 12 idle-prompt files, 18 schedule files
(47 new files).
## File-size impact
| Before (main) | After Phase 1 | After Phase 2 | Reduction |
|---|---|---|---|
| 1801 lines | 1687 lines | 676 lines | **-62.5%** |
| 108 KB | 101 KB | 35 KB | **-67%** |
org.yaml is now pure structural scaffolding (name / role / tier / model /
canvas / plugins / channels / children / category_routing / schedules
metadata). Readable end-to-end on one screen per team.
## How the migration was driven
A Python round-trip script (using `ruamel.yaml` to preserve comments +
formatting) walked the workspace tree recursively, wrote prompts to
files keyed by `files_dir`, and replaced inline keys with `*_file:` refs.
Zero manual YAML hand-editing beyond the Phase 1 Documentation Specialist
proof. Script is one-shot; not committed.
Slug convention for schedule files: lowercase the schedule name, replace
non-alphanumeric with `-`, collapse, cap 60 chars. Examples:
- "Orchestrator pulse" → `orchestrator-pulse.md`
- "Hourly template fitness audit" → `hourly-template-fitness-audit.md`
- "Code quality audit (every 12h)" → `code-quality-audit-every-12h.md`
## Backwards compatibility
Fully compatible — Phase 1's resolver prefers inline when both are set,
so a future one-off experiment can still drop inline YAML. The migration
doesn't remove inline support, just stops using it.
## Verification
- [x] `python -c "yaml.safe_load(...)"` on edited org.yaml — parses clean
- [x] Walk-and-inspect script: every workspace has exactly the expected
`*_file:` refs, zero `INLINE_*` markers remain
- [x] All 47 extracted .md files non-empty + trimmed
- [x] `go test -run 'TestResolvePromptRef|TestOrgYAML|TestInitialPrompt'`
passes (from Phase 1 platform work)
- [ ] Post-merge: live `POST /org/import` against a fresh workspace,
diff the resulting `/configs/config.yaml` + `workspace_schedules`
rows against the pre-migration values (should be identical bodies)
## What's next
- **Phase 3 (queued):** YAML `!include` directive for org.yaml; split the
remaining 676 lines into `teams/{research,dev,marketing,ops}.yaml`.
- **Phase 4 (queued):** per-workspace atomization; each role owns its
own `workspace.yaml` manifest.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Two recent platform-level security changes (#319 channel_config
encryption, #337 constant-time webhook_secret compare) were not
reflected in the Security Auditor's system prompt or the schedule cron
prompt. That meant the auditor wouldn't proactively look for the
*next* instance of either class — a new credential field added to
channel_config without being added to sensitiveFields, or a new
secret comparison using raw `!=`, would slip through until a human
happened to notice.
Updated two files:
1. org-templates/molecule-dev/security-auditor/system-prompt.md
Added two bullets to "What You Check":
- Secret comparisons must use subtle.ConstantTimeCompare /
crypto.timingSafeEqual (cites #337 as the repo's recent instance)
- Secret storage at rest: any new channel_config credential field
must be added to sensitiveFields and exercised in both the
Encrypt (write) and Decrypt (read) boundary helpers, and the
ec1: prefix must never leak into API responses (cites #319)
2. org-templates/molecule-dev/org.yaml
Same two checks added to the Security Auditor's 12-hour cron
prompt's "MANUAL REVIEW of every changed file" section. Wording
is concrete enough to paste into a grep: "flag any `!=` / `==` /
bytes.Equal against a user-supplied value that gates auth".
Pure config / prompt — no code changes, no tests to write. YAML parse
verified, TestPlugins_UnionWithDefaults still passes.
Closes#342
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Closes#248. Three instances of the same YAML-injection bug class
(#221 name/role, #233 template path, #241 runtime/model) shipped in
this repo over the last weeks. The common root cause is the Security
Auditor's system prompt didn't list YAML injection as an explicit
check class, so audits missed the pattern every time.
Adds:
- "YAML injection" to the 'Think like an attacker' list in How You Work
- An explicit entry in What You Check with the three prior instances
cited so future auditors see the pattern and the fix shape
(double-quoted scalars or a proper YAML encoder)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>