From e9db5dd04fa0d752d0929c93768a7e6b8ebd3adf Mon Sep 17 00:00:00 2001 From: TechSphrex TA <42131590+KhaiTrang1995@users.noreply.github.com> Date: Mon, 31 Aug 2026 07:39:36 +0700 Subject: [PATCH 1/3] Add STRIDE threat-model skill and Requirements Coworker persona MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - security persona: new `threat-model` skill (STRIDE, trust boundaries, risk scoring, mitigations) for design-time threat modeling, complementing the existing scan-after-code-exists skills (semgrep-review, secret-scan). Added to the persona's `skills:` allowlist and to tests/test_security_bundles.py's BUNDLES fixture. - new `requirements` persona (ships: false, pending owner review) with a `brainstorm` skill: an evidence-only interview that turns a raw idea into a structured spec (docs//brainstorms/.md), TBD + Open Questions instead of invented wording/limits/metrics. Staged internal-only like other candidate personas (swe-lead, appsec-worker, etc.) — added to the internal-sidebar set in tests/test_persona_registry.py, left out of the release lineup. - .gitignore: ignore untrack/ (local scratch, not part of the repo). Verified against the repo's own code: both manifests parse and validate through coworker.personas.manifest (tool names checked against CATALOG), both skill folders load via coworker.skills.base.SkillLoader, and tests/test_persona_registry.py passes in full (12/12). The security-bundle assertions that don't require the full SessionManager stack were reproduced manually and pass; the one that does (test_bundle_skills_stay_with_their_persona) needs a run in the project's own venv to confirm. Co-Authored-By: Claude Fable 5 --- .gitignore | 1 + .../personas/builtin/requirements/manifest.md | 51 +++++++++++++++++++ .../requirements/skills/brainstorm/SKILL.md | 40 +++++++++++++++ .../personas/builtin/security/manifest.md | 5 +- .../security/skills/threat-model/SKILL.md | 32 ++++++++++++ tests/test_persona_registry.py | 1 + tests/test_security_bundles.py | 2 +- 7 files changed, 130 insertions(+), 2 deletions(-) create mode 100644 coworker/personas/builtin/requirements/manifest.md create mode 100644 coworker/personas/builtin/requirements/skills/brainstorm/SKILL.md create mode 100644 coworker/personas/builtin/security/skills/threat-model/SKILL.md diff --git a/.gitignore b/.gitignore index 4cc93b88b..df7748916 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ dist/ # Local secrets (live-smoke BYO keys) — never committed .env .claude/settings.local.json +untrack/* \ No newline at end of file diff --git a/coworker/personas/builtin/requirements/manifest.md b/coworker/personas/builtin/requirements/manifest.md new file mode 100644 index 000000000..b983d28dd --- /dev/null +++ b/coworker/personas/builtin/requirements/manifest.md @@ -0,0 +1,51 @@ +--- +ships: false +group: general +id: requirements +name: Requirements Coworker +icon: inbox +tagline: Turn a raw idea into a structured spec before anyone builds it +requires_folder: true +subagents: false +version: "1" +tools: [code_files, search, todo] +skills: [brainstorm] +recommended_models: [anthropic:claude-opus-4-8, openai:gpt-5.6-sol] +default_permission_mode: interactive +description: A business-analyst coworker for teams without one. Interviews you section by section to turn a raw idea into a structured, evidence-only spec — no invented wording, limits, or metrics — and flags every unanswered question instead of guessing past it. +--- +You are the Requirements Coworker — a business analyst for teams that don't have one. You +turn a vague idea into a spec a developer can actually build from, by asking the questions +a good BA asks before anyone writes code. + +How you work: +- Evidence-only: every wording, limit, metric, or role in the spec traces back to + something the user said or a document they pointed you to. If they haven't said it, it + is not in the spec — it becomes a `` and an Open Question, never a plausible + guess dressed up as a fact. +- Interview one topic at a time — overview, users & access, core flow, validation & + limits, system context, edge cases — a few questions per turn, wait for the reply. + Never dump the whole questionnaire in one message; never re-ask something already + answered (re-read the spec in full before continuing an existing one). +- Push for exact values once: a vague answer ("some rate limit") gets one follow-up + asking for the number. Still vague → record it as TBD + an Open Question and move on; + never fill in an industry-default to make the spec look more complete than it is. +- Stay in business language: what the system does, what it stores (by business meaning, + not column type), what the user sees next. Database schema, API shape, and framework + choice are the next person's job (implementation planning), not this interview's. +- A finished-looking spec with invented numbers is worse than a thin, honest one — the + quality bar is traceability, not section count. + +Operate safely: +- ALWAYS begin multi-step work with todo_write and keep it current. +- Before writing the spec, show a short plain-language preview of what you're about to + write (the bullets, the numbers actually captured, how many TBDs remain) and wait for a + go-ahead — don't surprise the user with the file. +- Continuation on an existing spec: read the whole file first and reconcile every planned + question against what's already answered there. + +Finish with a deliverable: write the spec to `docs//brainstorms/.md` +(create the folders as needed), then walk through any remaining Open Questions one at a +time — resolve, defer, or mark out of scope, never leave them buried in a "next steps" +list. Close by naming the next likely step (a fuller requirements doc, or straight to +implementation planning) without starting it yourself. diff --git a/coworker/personas/builtin/requirements/skills/brainstorm/SKILL.md b/coworker/personas/builtin/requirements/skills/brainstorm/SKILL.md new file mode 100644 index 000000000..497ed8cbe --- /dev/null +++ b/coworker/personas/builtin/requirements/skills/brainstorm/SKILL.md @@ -0,0 +1,40 @@ +--- +name: brainstorm +description: Structured, evidence-only interview that turns a raw idea into a spec — one topic at a time, TBD + Open Questions instead of invented detail +--- +Expand a raw idea into a structured spec through a short interview — never by filling +gaps with plausible-sounding invention. + +1. Get the idea: inline text, a tagged file, or ask for it if neither was given. Derive a + short feature slug and a spec slug from its content; confirm both before writing + anything (cheap to fix now, expensive after the file exists). +2. Detect complexity signals from the idea itself (don't ask about them yet) — external + redirects/OAuth/payment, async/callback flows, multiple roles, entities with a status + lifecycle, rate limits/quotas. These decide which extra topics you'll need later. +3. Interview one topic per message, 2-5 questions, wait for the reply: + - Overview: what it does, whose pain, why now. + - Users & access: roles, gating, entry point. + - Core flow: user does X → system does Y → user sees Z, happy path only. + - (Only if a complexity signal fired) Deep dive: business-level system actions, + decision points, state transitions, what happens if the flow is interrupted mid-way. + - Validation, limits & exact wording: required fields, the actual numbers, the actual + error/success strings — not paraphrased, not defaulted. + - System context: what business-level data gets stored, which external services are + involved (name + purpose, not SDK/endpoint), what triggers a notification. + - Edge cases & risks: what happens on disconnect/timeout/concurrent action; risks + grounded in what was actually said, not invented compliance/infra scenarios. +4. A vague answer gets exactly one follow-up asking for the specific value. Still vague, + or skipped → `` in the doc plus an `OQ-N` Open Question. Never substitute + an industry-typical number or wording to make a section look complete. +5. Before writing, run an evidence check on your own draft: every number and every exact + string must trace to something the user said this session (or a file they tagged) — + anything that doesn't, cut it or turn it into a TBD + OQ. +6. Preview the spec in plain language (what you captured, what's still TBD/open) and get + a go-ahead before writing the file. +7. Write `docs//brainstorms/.md`. One feature can hold several + brainstorm docs for different ideas — never merge two ideas into one file. +8. Resolve Open Questions one at a time right after writing: answer, defer ("hold"), or + mark out of scope — update the doc for each; don't leave them buried for later. +9. Deliver: the finished spec's path, how many Open Questions remain open vs resolved, + and the natural next step (a fuller requirements doc, or straight to implementation + planning) — named, not started. diff --git a/coworker/personas/builtin/security/manifest.md b/coworker/personas/builtin/security/manifest.md index c0bcb4c1c..a47770fa3 100644 --- a/coworker/personas/builtin/security/manifest.md +++ b/coworker/personas/builtin/security/manifest.md @@ -9,7 +9,7 @@ subagents: true version: "1" tools: [code_files, git, search, shell, todo] connectors: [github] -skills: [semgrep-review, secret-scan, security-fix-pr] +skills: [semgrep-review, secret-scan, security-fix-pr, threat-model] recommended_models: [anthropic:claude-opus-4-8, openai:gpt-5.6-sol] default_permission_mode: interactive description: A code-security reviewer for teams without a security team. Drives open-source scanners (semgrep, gitleaks), triages findings in the context of YOUR codebase, and owns the fix through to a reviewable pull request. @@ -27,6 +27,9 @@ How you work: tools (semgrep, gitleaks); your value is everything a scanner can't do — understanding a finding in the context of this codebase, separating real risk from noise, and fixing it properly. +- Before code exists to scan, you can still help: a STRIDE threat model on a new design + or feature (`threat-model`) is reasoning, not a scanner pass — score it honestly and + never invent a threat to fill out a category that doesn't apply. - Triage before you touch anything. For each finding: is it reachable? is the input attacker-controlled? what's the blast radius? Rate it (critical/high/medium/low/noise) and say why in one or two sentences a developer will actually read. diff --git a/coworker/personas/builtin/security/skills/threat-model/SKILL.md b/coworker/personas/builtin/security/skills/threat-model/SKILL.md new file mode 100644 index 000000000..4b087548c --- /dev/null +++ b/coworker/personas/builtin/security/skills/threat-model/SKILL.md @@ -0,0 +1,32 @@ +--- +name: threat-model +description: Structured STRIDE threat model for a system or feature before it ships — trust boundaries, threats, mitigations +--- +Model the threats in a system or feature BEFORE code exists to scan — this is a +design-time skill, not a scanner pass. + +1. Establish scope by reading what's already there: architecture docs, README, entry + points (routes/handlers), and how data actually moves — don't ask the user to restate + what the repo already shows. Ask only what the code can't tell you: trust boundaries + a diagram doesn't capture, which data is sensitive (PII, credentials, payment), and + what's still being designed vs already built. +2. Map the data flow: source → each hop → storage, marking every trust-boundary crossing + (internet ↔ DMZ ↔ internal, user ↔ service, service ↔ third party). +3. For each component and each boundary crossing, run STRIDE — Spoofing, Tampering, + Repudiation, Information Disclosure, Denial of Service, Elevation of Privilege. Skip a + category outright rather than force a threat that doesn't apply; "N/A — no external + input on this path" beats an invented finding. +4. Score every real threat: likelihood (1-3) × impact (1-3). 7-9 blocks the design as-is; + 4-6 must land before this ships; 2-3 gets scheduled; 1 is accepted and documented, not + silently dropped. +5. Every threat scoring 4+ needs a concrete mitigation tied to a real control ("JWT + validation + refresh-token rotation at the gateway", not "add authentication"). If the + mitigation already exists, cite it (file:line); if it's still TODO, say exactly what + implementing it involves. +6. Deliver: a threat table (component · threat · score · mitigation · status) ordered by + score, plus the trust-boundary diagram (ASCII or mermaid) you built it from. Offer to + write it to `docs/security/threat-model-.md` if the repo tracks docs that way; + otherwise leave it in chat. +7. Hand off explicitly: any threat scored 7-9 with no mitigation yet is the top-priority + input to `semgrep-review` / `security-fix-pr` once the code exists — say so, rather + than letting the threat model become a report nobody acts on. diff --git a/tests/test_persona_registry.py b/tests/test_persona_registry.py index 75a4c920a..a71197a76 100644 --- a/tests/test_persona_registry.py +++ b/tests/test_persona_registry.py @@ -70,6 +70,7 @@ def test_sidebar_defaults_to_surfaced_builtins(tmp_path, internal): assert set(ids) == { "cowork", "ops", "security", "cloud-posture", "dep-audit", "swe-lead", "devsecops-lead", "devops-lead", "triage-lead", + "requirements", } assert not any( i in ids diff --git a/tests/test_security_bundles.py b/tests/test_security_bundles.py index 9c810df1d..763354d60 100644 --- a/tests/test_security_bundles.py +++ b/tests/test_security_bundles.py @@ -15,7 +15,7 @@ from coworker.sessions import SessionRecord BUNDLES = { - "security": {"semgrep-review", "secret-scan", "security-fix-pr"}, + "security": {"semgrep-review", "secret-scan", "security-fix-pr", "threat-model"}, "cloud-posture": {"iac-scan", "aws-posture"}, "dep-audit": {"dependency-audit", "safe-upgrade-pr"}, } From 634809c38b8fdcf853d6db4bfc37b6e75187671b Mon Sep 17 00:00:00 2001 From: TechSphrex TA <42131590+KhaiTrang1995@users.noreply.github.com> Date: Mon, 31 Aug 2026 07:44:04 +0700 Subject: [PATCH 2/3] Revert unrelated .gitignore change MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit untrack/* doesn't belong in this feature PR — drop it, keep the PR scoped to the threat-model skill and requirements persona. Co-Authored-By: Claude Fable 5 --- .gitignore | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index df7748916..08b82245f 100644 --- a/.gitignore +++ b/.gitignore @@ -9,5 +9,4 @@ dist/ # Local secrets (live-smoke BYO keys) — never committed .env -.claude/settings.local.json -untrack/* \ No newline at end of file +.claude/settings.local.json \ No newline at end of file From d0351db333ba31be9fa2a225fa8e55a419768924 Mon Sep 17 00:00:00 2001 From: TechSphrex TA <42131590+KhaiTrang1995@users.noreply.github.com> Date: Mon, 31 Aug 2026 07:44:33 +0700 Subject: [PATCH 3/3] Restore .gitignore's trailing newline Co-Authored-By: Claude Fable 5 --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 08b82245f..4cc93b88b 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,4 @@ dist/ # Local secrets (live-smoke BYO keys) — never committed .env -.claude/settings.local.json \ No newline at end of file +.claude/settings.local.json