cleanup(engineering): address remaining 7 polish items from PR #718 bot review

Bundle of low-medium-severity follow-ups that were deferred when PR #720
landed the 3 blocking bugs. None of these silently break correctness —
they're discoverability, consistency, and convention gaps.

Bugs / code-quality:

1. fullstack_decision_engine.py: asymmetric cadence matching
   `inputs.cadence in target or target in inputs.cadence` produced
   asymmetric results — "per-pr" matched "per-pr-with-gates" but not
   vice versa. Profile cadences are intentional alternatives joined
   by "-or-" (e.g. "weekly-or-on-demand" → {weekly, on-demand}); now
   parsed explicitly with "-with-..." modifier suffixes stripped.

   Verified:
     cadence=per-pr → matches per-pr, per-pr-with-gates, daily-or-per-pr
     cadence=daily  → matches daily-or-per-pr (only)
     cadence=on-demand → matches weekly-or-on-demand

2. fullstack_decision_engine.py: rename weight_total/weight_matched
   to w_total/w_matched. Backend and frontend engines already use the
   short form; this aligns the three files as a family.

3. sync-gemini-skills.py: 3-way name collision in dedup logic
   The naive `if name in seen_names: name = parent-name` handled one
   collision but not two. Three "status" skills under "skills" parent
   dirs produced two entries both named "skills-status". Now suffixes
   with -2, -3, ... so each entry has a unique index name. Eliminates
   the duplicate-name ambiguity surfaced when checking PR #713.

Discoverability:

4. senior-fullstack/SKILL.md: surface fullstack_decision_engine.py in
   the labeled "Tools" section at the top. Previously only mentioned
   inline in the body (5 references buried in the Stack Decision Matrix
   section); not findable when scanning the SKILL.md.

Conventions / v2.8.0 compliance:

5. commands/cs-{fullstack,backend,frontend}-review.md: add explicit
   "## Forcing-question library" section header per the v2.8.0
   convention. Each lists the 7 questions inline with a pointer to
   the canonical reference file.

6. agents/engineering/cs-{fullstack,backend,frontend}-engineer.md:
   alphabetize the specialist list in the description field (annotated
   that workflow body order remains dependency-driven). Makes the
   three agent descriptions consistent as a family.

7. agents/engineering/cs-{backend,frontend}-engineer.md: promote the
   "Cross-agent invocation" content out of Workflow 3 into a dedicated
   "## When invoked as fork target" section with an explicit question-
   skip table per parent agent (cs-fullstack-engineer, cs-cto-advisor,
   cs-vpe-advisor, cs-ciso-advisor for backend; cs-fullstack-engineer,
   cs-content-creator, cs-product-manager for frontend). Closes the
   cross-agent contract gap the bot flagged.

Not changed:

- CLAUDE.md plugin-schema section (already corrected in #715; bot's
  "stale text" claim was incorrect — it was reading the cumulative diff)
- Workflow body specialist order (intentional dependency order; would
  break the SLO-first → API → DB → migration → observability sequence)

Verification:
- All 3 decision engines: --sample → exit 0
- Cadence matching: 3 test cases pass cleanly
- check_plugin_json.py --all → 0 FAIL, 0 WARN, 69 OK
- sync-gemini-skills.py → 392 unique names (was 391 unique / 1 dupe)
This commit is contained in:
Claude 2026-05-21 13:47:08 +00:00
parent 30ff797b48
commit 5954dfcce1
No known key found for this signature in database
11 changed files with 119 additions and 25 deletions

View file

@ -31,7 +31,7 @@
{
"name": "cs-backend-engineer",
"category": "agent",
"description": "Backend-engineering orchestrator. Walks the 7 Matt Pocock forcing questions (read/write ratio + QPS, tenancy, sync vs async, data sensitivity, pattern, RPO/RTO, SLO), picks the language + pattern profile, forks into specialists (api-design-reviewer, database-designer, migration-architect, slo-architect, observability-designer) rather than reimplementing their scope. Forks own context. Invoke via /cs:backend-review or Agent({subagent_type:\"cs-backend-engineer\",...})."
"description": "Backend-engineering orchestrator. Walks the 7 Matt Pocock forcing questions (read/write ratio + QPS, tenancy, sync vs async, data sensitivity, pattern, RPO/RTO, SLO), picks the language + pattern profile, forks into specialists (api-design-reviewer, database-designer, migration-architect, observability-designer, slo-architect \u2014 listed alphabetically; workflow order is dependency-driven) rather than reimplementing their scope. Forks own context. Invoke via /cs:backend-review or Agent({subagent_type:\"cs-backend-engineer\",...})."
},
{
"name": "cs-ceo-advisor",
@ -66,12 +66,12 @@
{
"name": "cs-frontend-engineer",
"category": "agent",
"description": "Frontend-engineering orchestrator. Walks the 7 Matt Pocock forcing questions (device, LCP target, rendering, bundle budget, SEO vs auth, design system, WCAG), picks the framework/rendering profile, forks into specialists (a11y-audit, performance-profiler, epic-design, apple-hig-expert, playwright-pro) rather than reimplementing their scope. Forks own context. Invoke via /cs:frontend-review or Agent({subagent_type:\"cs-frontend-engineer\",...})."
"description": "Frontend-engineering orchestrator. Walks the 7 Matt Pocock forcing questions (device, LCP target, rendering, bundle budget, SEO vs auth, design system, WCAG), picks the framework/rendering profile, forks into specialists (a11y-audit, apple-hig-expert, epic-design, performance-profiler, playwright-pro \u2014 listed alphabetically; workflow order is dependency-driven) rather than reimplementing their scope. Forks own context. Invoke via /cs:frontend-review or Agent({subagent_type:\"cs-frontend-engineer\",...})."
},
{
"name": "cs-fullstack-engineer",
"category": "agent",
"description": "Fullstack-engineering orchestrator. Walks the Matt Pocock 7-question forcing-question grill, runs the deterministic profile picker, then forks into the POWERFUL-tier specialists (api-design-reviewer, database-designer, slo-architect, ci-cd-pipeline-builder, performance-profiler) rather than reimplementing their scope. Forks own context so heavy ingestion does not pollute parent thread. Invoke via /cs:fullstack-review or Agent({subagent_type:\"cs-fullstack-engineer\",...})."
"description": "Fullstack-engineering orchestrator. Walks the Matt Pocock 7-question forcing-question grill, runs the deterministic profile picker, then forks into the POWERFUL-tier specialists (api-design-reviewer, ci-cd-pipeline-builder, database-designer, performance-profiler, slo-architect \u2014 listed alphabetically; workflow order is dependency-driven) rather than reimplementing their scope. Forks own context so heavy ingestion does not pollute parent thread. Invoke via /cs:fullstack-review or Agent({subagent_type:\"cs-fullstack-engineer\",...})."
},
{
"name": "cs-growth-strategist",
@ -1009,7 +1009,7 @@
"description": ">-"
},
{
"name": "skills-status",
"name": "skills-status-2",
"category": "engineering",
"description": "Memory health dashboard showing line counts, topic files, capacity, stale entries, and recommendations."
},

View file

@ -0,0 +1 @@
../../../engineering-team/self-improving-agent/skills/status/SKILL.md

View file

@ -1,6 +1,6 @@
---
name: cs-backend-engineer
description: Backend-engineering orchestrator. Walks the 7 Matt Pocock forcing questions (read/write ratio + QPS, tenancy, sync vs async, data sensitivity, pattern, RPO/RTO, SLO), picks the language + pattern profile, forks into specialists (api-design-reviewer, database-designer, migration-architect, slo-architect, observability-designer) rather than reimplementing their scope. Forks own context. Invoke via /cs:backend-review or Agent({subagent_type:"cs-backend-engineer",...}).
description: Backend-engineering orchestrator. Walks the 7 Matt Pocock forcing questions (read/write ratio + QPS, tenancy, sync vs async, data sensitivity, pattern, RPO/RTO, SLO), picks the language + pattern profile, forks into specialists (api-design-reviewer, database-designer, migration-architect, observability-designer, slo-architect — listed alphabetically; workflow order is dependency-driven) rather than reimplementing their scope. Forks own context. Invoke via /cs:backend-review or Agent({subagent_type:"cs-backend-engineer",...}).
skills: engineering-team/senior-backend
domain: engineering
tools: [Read, Write, Bash, Grep, Glob]
@ -84,11 +84,20 @@ The first question kills more bad architecture than any other. Without QPS + rat
### Workflow 3: Cross-agent invocation from `cs-fullstack-engineer` or `cs-cto-advisor`
**Steps:**
See **"When invoked as fork target"** below for the question-skip contract.
1. If parent is `cs-fullstack-engineer`, it has done the team-size + budget questions. Skip to Q1 (QPS), Q3 (sync/async), Q5 (pattern).
2. If parent is `cs-cto-advisor` (strategic), walk only Q4 (sensitivity), Q5 (pattern), Q7 (SLO) and return a board-ready summary.
3. **Return a digest the parent can quote.**
## When invoked as fork target
When this agent is forked from another orchestrator (rather than invoked directly by a user), assume the parent has already collected the answers in its own grill and skip the redundant questions. Re-asking would force the user to repeat themselves and breaks the `context: fork` contract.
| Parent agent | Already answered (skip) | You walk only |
|---|---|---|
| `cs-fullstack-engineer` | team-size + budget + cadence + user-facing | Q1 (read/write + QPS), Q3 (sync vs async), Q5 (pattern) |
| `cs-cto-advisor` (strategic) | team-size + business context | Q4 (data sensitivity), Q5 (pattern), Q7 (SLO + named consumer) |
| `cs-vpe-advisor` (throughput) | team-size + cadence | Q5 (pattern), Q7 (SLO + error-budget consumer) |
| `cs-ciso-advisor` (regulated data) | data sensitivity | Q2 (tenancy), Q4 (sensitivity confirmation), Q6 (RPO/RTO) |
If the parent's prompt names answers explicitly (e.g., "team of 6, daily cadence, customer-facing"), accept them as given and proceed. Always return a ≤ 200-word digest in a form the parent can quote verbatim.
## Karpathy gate (pre-commit)

View file

@ -1,6 +1,6 @@
---
name: cs-frontend-engineer
description: Frontend-engineering orchestrator. Walks the 7 Matt Pocock forcing questions (device, LCP target, rendering, bundle budget, SEO vs auth, design system, WCAG), picks the framework/rendering profile, forks into specialists (a11y-audit, performance-profiler, epic-design, apple-hig-expert, playwright-pro) rather than reimplementing their scope. Forks own context. Invoke via /cs:frontend-review or Agent({subagent_type:"cs-frontend-engineer",...}).
description: Frontend-engineering orchestrator. Walks the 7 Matt Pocock forcing questions (device, LCP target, rendering, bundle budget, SEO vs auth, design system, WCAG), picks the framework/rendering profile, forks into specialists (a11y-audit, apple-hig-expert, epic-design, performance-profiler, playwright-pro — listed alphabetically; workflow order is dependency-driven) rather than reimplementing their scope. Forks own context. Invoke via /cs:frontend-review or Agent({subagent_type:"cs-frontend-engineer",...}).
skills: engineering-team/senior-frontend
domain: engineering
tools: [Read, Write, Bash, Grep, Glob]
@ -88,11 +88,19 @@ Do not skip ahead. Do not bundle. The primary device decides every downstream ch
### Workflow 3: Cross-agent invocation from `cs-fullstack-engineer` or `cs-content-creator`
**Steps:**
See **"When invoked as fork target"** below for the question-skip contract.
1. If the parent is `cs-fullstack-engineer`, it has already done the team-size + cadence questions. Skip to Q1 (device), Q3 (rendering), Q7 (WCAG).
2. If the parent is `cs-content-creator` (marketing), default to `astro-or-static` profile — skip to Q4 (bundle) + Q7 (WCAG).
3. **Return a digest the parent can quote verbatim.**
## When invoked as fork target
When this agent is forked from another orchestrator (rather than invoked directly by a user), assume the parent has already collected the answers in its own grill and skip the redundant questions. Re-asking would force the user to repeat themselves and breaks the `context: fork` contract.
| Parent agent | Already answered (skip) | You walk only |
|---|---|---|
| `cs-fullstack-engineer` | team-size + cadence + user-facing + budget | Q1 (primary device), Q3 (rendering), Q7 (WCAG + a11y owner) |
| `cs-content-creator` (marketing copy) | brand voice + surface = marketing | Default to `astro-or-static` profile; walk only Q4 (bundle) + Q7 (WCAG) |
| `cs-product-manager` (feature spec) | user persona + surface | Q1 (device), Q2 (LCP target), Q5 (SEO vs auth) |
If the parent's prompt names answers explicitly (e.g., "mobile-4G primary, LCP target 2000ms"), accept them as given and proceed. Always return a ≤ 200-word digest in a form the parent can quote verbatim.
## Karpathy gate (pre-commit)

View file

@ -1,6 +1,6 @@
---
name: cs-fullstack-engineer
description: Fullstack-engineering orchestrator. Walks the Matt Pocock 7-question forcing-question grill, runs the deterministic profile picker, then forks into the POWERFUL-tier specialists (api-design-reviewer, database-designer, slo-architect, ci-cd-pipeline-builder, performance-profiler) rather than reimplementing their scope. Forks own context so heavy ingestion does not pollute parent thread. Invoke via /cs:fullstack-review or Agent({subagent_type:"cs-fullstack-engineer",...}).
description: Fullstack-engineering orchestrator. Walks the Matt Pocock 7-question forcing-question grill, runs the deterministic profile picker, then forks into the POWERFUL-tier specialists (api-design-reviewer, ci-cd-pipeline-builder, database-designer, performance-profiler, slo-architect — listed alphabetically; workflow order is dependency-driven) rather than reimplementing their scope. Forks own context so heavy ingestion does not pollute parent thread. Invoke via /cs:fullstack-review or Agent({subagent_type:"cs-fullstack-engineer",...}).
skills: engineering-team/senior-fullstack
domain: engineering
tools: [Read, Write, Bash, Grep, Glob]

View file

@ -9,6 +9,18 @@ Use the `cs-backend-engineer` agent (uses `context: fork`) to handle this inquir
**$ARGUMENTS**
## Forcing-question library
Canonical source: `engineering-team/skills/senior-backend/references/forcing_questions.md` (7 questions, one-per-turn, recommendation + canon citation per question).
1. Read/write ratio + one-year p99 QPS
2. Tenancy model (single / shared / isolated multi-tenant)
3. Sync request/response vs async (queue) vs event-driven
4. Data sensitivity tier (public / internal / PII / PHI / PCI)
5. Monolith / modular monolith / microservices (team-size justification)
6. RPO and RTO
7. SLO + named error-budget consumer
## Routing protocol
1. **Walk the 7 forcing questions** in `engineering-team/skills/senior-backend/references/forcing_questions.md`. One per turn. Recommend with cited canon. Track in `/tmp/backend-grill-<date>.md`.

View file

@ -9,6 +9,18 @@ Use the `cs-frontend-engineer` agent (uses `context: fork`) to handle this inqui
**$ARGUMENTS**
## Forcing-question library
Canonical source: `engineering-team/skills/senior-frontend/references/forcing_questions.md` (7 questions, one-per-turn, recommendation + canon citation per question).
1. Primary device + network (desktop-fiber / mobile-4G / low-end Android / corporate)
2. LCP target on primary device (milliseconds)
3. Server Components vs SPA vs SSR vs SSG
4. JS bundle budget per route (KB gzipped)
5. SEO-dependent or auth-walled
6. Design-system location (Figma + tokens / ad-hoc Tailwind / headless UI)
7. WCAG target (AA / AAA / best-effort) + accessibility owner
## Routing protocol
1. **Walk the 7 forcing questions** in `engineering-team/skills/senior-frontend/references/forcing_questions.md`. One per turn. Recommend with cited canon. Track in `/tmp/frontend-grill-<date>.md`.

View file

@ -9,6 +9,18 @@ Use the `cs-fullstack-engineer` agent (which uses `context: fork` to keep the pa
**$ARGUMENTS**
## Forcing-question library
Canonical source: `engineering-team/skills/senior-fullstack/references/forcing_questions.md` (7 questions, one-per-turn, recommendation + canon citation per question).
1. Team size now + 12-month headcount
2. Deployment cadence (per-PR / daily / weekly / quarterly)
3. Customer-facing / internal tool / marketing site
4. One-year p50 + p99 traffic forecast
5. Hiring-against vs training-into the stack
6. Year-one monthly cloud + SaaS budget ceiling
7. Three verifiable success criteria with numeric targets
## Routing protocol
1. **Walk the 7 forcing questions** in `engineering-team/skills/senior-fullstack/references/forcing_questions.md`. One per turn. Recommend the answer with cited canon. Track in `/tmp/fullstack-grill-<date>.md`.

View file

@ -34,6 +34,34 @@ Use this skill when you hear:
## Tools
### Decision Engine
Deterministic profile picker. Given four assumptions (team-size, cadence, user-facing, budget) plus optional traffic/sensitivity inputs, ranks the four built-in profiles and returns the matched profile with SLO floor and named approver chain. Refuses to recommend a profile without the four required inputs.
**Usage:**
```bash
# See all options
python scripts/fullstack_decision_engine.py --help
# Run against a sample input
python scripts/fullstack_decision_engine.py --sample
# Pick a profile from real inputs
python scripts/fullstack_decision_engine.py \
--team-size-12mo 8 --cadence daily --user-facing true --budget 5000 \
--traffic-p99-rps 50 --data-sensitivity pii-only
# JSON output for downstream tools
python scripts/fullstack_decision_engine.py --sample --output json
```
Returns: matched profile name, score, matched/violated constraints, stack recommendation, anti-recommendations, SLO floor, named-approver chain, and canon references.
The engine encodes the same matrix the conversational grill walks through — use it directly when inputs are already known, or via the `cs-fullstack-engineer` agent for the question-by-question grill.
---
### Project Scaffolder
Generates fullstack project structures with boilerplate code.

View file

@ -107,14 +107,14 @@ def score_profile(profile: dict[str, Any], inputs: Inputs) -> Match:
constraints = profile.get("constraints", {})
matched: list[str] = []
violated: list[str] = []
weight_total = 0.0
weight_matched = 0.0
w_total = 0.0
w_matched = 0.0
def check(label: str, ok: bool, weight: float) -> None:
nonlocal weight_total, weight_matched
weight_total += weight
nonlocal w_total, w_matched
w_total += weight
if ok:
weight_matched += weight
w_matched += weight
matched.append(label)
else:
violated.append(label)
@ -139,7 +139,11 @@ def score_profile(profile: dict[str, Any], inputs: Inputs) -> Match:
)
if "deployment_cadence" in constraints:
target = constraints["deployment_cadence"]
ok = inputs.cadence in target or target in inputs.cadence
# Profile cadences are explicit alternatives joined by "-or-",
# e.g. "weekly-or-on-demand" → {"weekly", "on-demand"}.
# Modifier suffixes like "-with-gates" are stripped for matching.
allowed = {a.split("-with-")[0] for a in target.split("-or-")}
ok = inputs.cadence in allowed
check(f"cadence ~ {target}", ok, weight=1.5)
if "cloud_budget_monthly_usd_ceiling" in constraints:
check(
@ -164,7 +168,7 @@ def score_profile(profile: dict[str, Any], inputs: Inputs) -> Match:
weight=1.0,
)
score = weight_matched / weight_total if weight_total > 0 else 0.0
score = w_matched / w_total if w_total > 0 else 0.0
return Match(
profile_name=name,
score=score,

View file

@ -72,10 +72,18 @@ def find_skills(repo_root: Path) -> List[Dict]:
else:
skill_name = skill_dir.name
# Handle duplicates by appending parent name
# Handle duplicates by appending parent name; if that still collides
# (e.g. three sources whose parent dir is "skills"), suffix with -2, -3, ...
# so each entry has a unique name in the index.
if skill_name in seen_names:
skill_name = f"{skill_dir.parent.name}-{skill_name}"
candidate = f"{skill_dir.parent.name}-{skill_name}"
n = 2
base = candidate
while candidate in seen_names:
candidate = f"{base}-{n}"
n += 1
skill_name = candidate
seen_names.add(skill_name)
# Determine category based on top-level folder