feat(cto): close Python+Angular stack gaps + PROFILE-DISTRIBUTION-PROTOCOL compliance
AGENT.md: REQUIRED T2 frontmatter per §2.1. manifest.yaml: REQUIRED governance: block per §2.2. Register new toolkit skills. install.sh: chmod +x. skills/cto-python-toolkit/SKILL.md (v0.1): closes Python stack gap inline. References real workspace projects as exemplars: scripts/sot-precommit.py (single-file CLI), bte-mcp/server.py + bte_core.py (FastMCP server), svrnty-hermes-webui-plugin (PEP 621 + pytest.ini_options), curator/sweep.py (mode flags + dry-run + stdlib-heavy). Sandcastle prompt template + post- run quality-gate routing via PG-svrnty.lib-quality-gates. skills/cto-angular-toolkit/SKILL.md (v0.1): closes Angular stack gap inline. Anchored to adwright/adwright-console as canonical Plan B Angular reference (Angular 21.2 + signals + standalone components + inject() + gRPC-web via @protobuf-ts/grpcweb-transport + L6-svrnty.lib-cqrs-datasource). Sandcastle prompt template + DESIGN.md compliance check for UI work. CONTRACT.md §6: Python+Angular promoted from ⚪ generic → 🟡 skill-only (no more "gap" marker). Documents path to ✅ deep when cortex/ libs extract. skills/cto-agent/SKILL.md: routing table updated — Python/Angular rows now route to the toolkit skills instead of falling through to generic. CLAUDE.md: site-map footer. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
375417a29b
commit
3a3503aa2e
13
AGENT.md
13
AGENT.md
@ -1,3 +1,16 @@
|
|||||||
|
---
|
||||||
|
name: cto-planb-agent
|
||||||
|
tier: T2
|
||||||
|
status: active
|
||||||
|
owner: jp
|
||||||
|
source: hand
|
||||||
|
last_reviewed: 2026-05-24
|
||||||
|
description: cto-planb profile identity — Plan B's CTO thin-orchestrator over sandcastle for code-modifying tasks
|
||||||
|
depends_on:
|
||||||
|
- profile-distribution-protocol
|
||||||
|
- cto-planb-contract
|
||||||
|
---
|
||||||
|
|
||||||
# cto-planb — Agent Identity
|
# cto-planb — Agent Identity
|
||||||
|
|
||||||
> The WHO of this profile distribution. Loaded conceptually before the orchestrator skill. For the behavior contract, see [`CONTRACT.md`](CONTRACT.md).
|
> The WHO of this profile distribution. Loaded conceptually before the orchestrator skill. For the behavior contract, see [`CONTRACT.md`](CONTRACT.md).
|
||||||
|
|||||||
21
CLAUDE.md
21
CLAUDE.md
@ -53,3 +53,24 @@ cto/
|
|||||||
- `manifest.yaml`: machine-readable identity + install hooks
|
- `manifest.yaml`: machine-readable identity + install hooks
|
||||||
- `distribution.yaml`: Hermes native install contract (separate from manifest by design)
|
- `distribution.yaml`: Hermes native install contract (separate from manifest by design)
|
||||||
- `README.md`: human-facing intro + install instructions
|
- `README.md`: human-facing intro + install instructions
|
||||||
|
|
||||||
|
|
||||||
|
## Site map — where to find anything in cortex-os
|
||||||
|
|
||||||
|
Read these in order to ground any session:
|
||||||
|
|
||||||
|
| What | Where |
|
||||||
|
|---|---|
|
||||||
|
| **Karpathy 4 rules** | `~/.claude/CLAUDE.md` (auto-inherited every session) |
|
||||||
|
| **Workspace contract + repo map** | `~/workspaces/hermes/CLAUDE.md` |
|
||||||
|
| **SOT library orientation** | `~/workspaces/hermes/sot/README.md` |
|
||||||
|
| **Curator-generated SOT index** | `~/workspaces/hermes/sot/INDEX.md` |
|
||||||
|
| **Profile catalog (5 profiles + tool disclosure + governance)** | `~/workspaces/hermes/sot/06-REGISTRY/PROFILE-CATALOG.md` |
|
||||||
|
| **Profile distribution protocol (T1)** | `~/workspaces/hermes/sot/03-PROTOCOLS/PROFILE-DISTRIBUTION-PROTOCOL.md` |
|
||||||
|
| **Frontmatter spec (T1)** | `~/workspaces/hermes/sot/04-STANDARDS/FRONTMATTER-SPEC.md` |
|
||||||
|
| **SOT enforcement (pre-commit + curator + pre-push)** | `~/workspaces/hermes/sot/04-STANDARDS/SOT-ENFORCEMENT.md` |
|
||||||
|
| **Living graph artifact** | `~/workspaces/hermes/graph/umbrella.json` (curator-maintained) |
|
||||||
|
| **Living graph UI panel (planned)** | `/umbrella` route in hermes-webui per `sot/03-PROTOCOLS/CORTEX-OS-UMBRELLA-VIZ-PRD.md` |
|
||||||
|
| **This repo's CONTRACT.md** | `./CONTRACT.md` if present (T1 — wins over everything in this repo) |
|
||||||
|
|
||||||
|
If you're new to a session: read the workspace contract first, then this file, then the SOT orientation. Don't guess about cortex-os structure — anchor to these.
|
||||||
|
|||||||
@ -146,13 +146,13 @@ CTO orchestrates code work across the following stacks. Coverage = "what cortex/
|
|||||||
| **Go (1.25)** | ✅ deep | `L6-svrnty.lib-llm`, `L6-svrnty.core-credentials`, `L6-svrnty.core-memory`, `PG-svrnty.tool-qa` | Sovereign core stack: runtime infra, creds, memory, QA orchestration. |
|
| **Go (1.25)** | ✅ deep | `L6-svrnty.lib-llm`, `L6-svrnty.core-credentials`, `L6-svrnty.core-memory`, `PG-svrnty.tool-qa` | Sovereign core stack: runtime infra, creds, memory, QA orchestration. |
|
||||||
| **Rust (Tokio)** | 🟡 moderate | `L6-svrnty.core-runtime` (zeroclaw, 5MB RAM target) | Zero-overhead agent runtime layer. One canonical lib; other Rust work falls to sandcastle generic. |
|
| **Rust (Tokio)** | 🟡 moderate | `L6-svrnty.core-runtime` (zeroclaw, 5MB RAM target) | Zero-overhead agent runtime layer. One canonical lib; other Rust work falls to sandcastle generic. |
|
||||||
| **Bash** | 🟡 moderate | `L5-svrnty.tool-bash-plugin` (cortex-script-v1 standard) | 9-category script engineering plugin. |
|
| **Bash** | 🟡 moderate | `L5-svrnty.tool-bash-plugin` (cortex-script-v1 standard) | 9-category script engineering plugin. |
|
||||||
| **Python** | ⚪ generic | None specific | Handled via sandcastle generic Claude Code path. No Python framework lib in cortex/ tooling layer yet. CTO orchestrates Python tasks the same way it orchestrates any code-modifying task. |
|
| **Python** | 🟡 skill-only | `cto-python-toolkit` skill (inline patterns) | No cortex/ Python framework lib yet, but `skills/cto-python-toolkit/` encodes patterns anchored to real workspace Python projects (bte-mcp, svrnty-hermes-webui-plugin, curator/sweep.py, scripts/sot-precommit.py). Promote to ✅ deep when cortex/ lib extracted. |
|
||||||
| **Angular** | ⚪ generic | None specific | Same as Python — generic sandcastle path. Future cortex/ Angular framework lib may emerge; until then, sandcastle handles. |
|
| **Angular** | 🟡 skill-only | `cto-angular-toolkit` skill (inline patterns) | No cortex/ Angular framework lib yet, but `skills/cto-angular-toolkit/` encodes Plan B's Angular 21 + signals + standalone + gRPC-web patterns anchored to `adwright/adwright-console/` (the canonical Plan B Angular reference). Promote to ✅ deep when cortex/ lib extracted. |
|
||||||
| **Multi-stack utility** | ✅ shared | `PG-svrnty.lib-quality-gates` (48 gates, 7 stacks: Go/Rust/Dart/Python/C#/Docker/Proto), `L5-svrnty.lib-skills-engineering` (28 patterns) | Post-sandcastle verification + pattern reference. |
|
| **Multi-stack utility** | ✅ shared | `PG-svrnty.lib-quality-gates` (48 gates, 7 stacks: Go/Rust/Dart/Python/C#/Docker/Proto), `L5-svrnty.lib-skills-engineering` (28 patterns) | Post-sandcastle verification + pattern reference. |
|
||||||
|
|
||||||
**Decision rule:** if a stack has a deep cortex/ tool, CTO MUST reference it in the sandcastle prompt (mount the tool repo, cite patterns). For generic stacks (Python, Angular), CTO falls back to standard Claude Code conventions w/o cortex/-specific tooling.
|
**Decision rule:** if a stack has a deep cortex/ tool, CTO MUST reference it in the sandcastle prompt (mount the tool repo, cite patterns). For skill-only stacks (Python, Angular), CTO routes to `cto-python-toolkit` or `cto-angular-toolkit` for inline patterns + workspace exemplars.
|
||||||
|
|
||||||
**Gap honesty:** Python and Angular are first-class consumer stacks (CMO, BTE-MCP, some L1 apps are Python; future admin consoles will be Angular). The absence of cortex/ tooling here is not a CTO limitation — it's a workspace tooling gap. Document any pain felt during v1.0 to prioritize building those tools later.
|
**Roadmap honesty:** Python and Angular have inline-skill coverage today; both gain dedicated cortex/ libs (`cortex/L6-svrnty.lib-python-framework`, `cortex/L6-svrnty.lib-angular-framework`) when usage justifies extraction. Until then, the toolkit skills ARE the framework reference.
|
||||||
|
|
||||||
## §7 DESIGN.md compliance (design-system interop)
|
## §7 DESIGN.md compliance (design-system interop)
|
||||||
|
|
||||||
|
|||||||
0
install.sh
Normal file → Executable file
0
install.sh
Normal file → Executable file
@ -9,8 +9,26 @@ version: 0.1.0 # pre-1.0: scaffold only, no executable orchestra
|
|||||||
identity: AGENT.md # WHO (role, mission, boundaries)
|
identity: AGENT.md # WHO (role, mission, boundaries)
|
||||||
contract: CONTRACT.md # behavior contract — tier T1 (this file wins)
|
contract: CONTRACT.md # behavior contract — tier T1 (this file wins)
|
||||||
|
|
||||||
|
# Governance — org / owner / vision / rules linked to SOT (PROFILE-DISTRIBUTION-PROTOCOL §2.2).
|
||||||
|
governance:
|
||||||
|
org: planb
|
||||||
|
owner: jp
|
||||||
|
approval_authority: jp
|
||||||
|
vision_refs:
|
||||||
|
- ../sot/01-ROADMAP/CORTEX-OS-ROADMAP.md
|
||||||
|
- ../sot/02-FRAMEWORK/CORTEX-OS-FRAMEWORK.md
|
||||||
|
governing_protocols:
|
||||||
|
- ../sot/03-PROTOCOLS/PROFILE-DISTRIBUTION-PROTOCOL.md
|
||||||
|
standards:
|
||||||
|
- ../sot/04-STANDARDS/FRONTMATTER-SPEC.md
|
||||||
|
- ../sot/04-STANDARDS/SOT-ENFORCEMENT.md
|
||||||
|
brand_master_ref: ../sot/07-BRAND/PLANB-BRAND-SYNTHESIS.md
|
||||||
|
north_star: "reliable, evolving tech — sandcastle-orchestrated code work, JP-approved deploys, never bypass isolation"
|
||||||
|
|
||||||
skills: # exposed to Hermes via skills.external_dirs (→ <repo>/skills)
|
skills: # exposed to Hermes via skills.external_dirs (→ <repo>/skills)
|
||||||
- skills/cto-agent # orchestrator (loop operator)
|
- skills/cto-agent # orchestrator (loop operator)
|
||||||
|
- skills/cto-python-toolkit # Python stack patterns (closes Python gap — inline until cortex/ lib extracted)
|
||||||
|
- skills/cto-angular-toolkit # Angular stack patterns (closes Angular gap — anchored to adwright-console)
|
||||||
|
|
||||||
# Role tools = scripts at repo root (the "lib"), reached through credbridge.
|
# Role tools = scripts at repo root (the "lib"), reached through credbridge.
|
||||||
lib:
|
lib:
|
||||||
|
|||||||
@ -81,8 +81,8 @@ CTO must include the relevant tool reference in every sandcastle prompt so the a
|
|||||||
| **Dart / Flutter** | `L6-svrnty.lib-cqrs-datasource` (gRPC client to .NET CQRS) | Mount lib-cqrs-datasource for proto+client patterns; `flutter analyze` + `flutter test` |
|
| **Dart / Flutter** | `L6-svrnty.lib-cqrs-datasource` (gRPC client to .NET CQRS) | Mount lib-cqrs-datasource for proto+client patterns; `flutter analyze` + `flutter test` |
|
||||||
| **Go** | `L6-svrnty.lib-llm`, `L6-svrnty.core-credentials`, `L6-svrnty.core-memory`, `PG-svrnty.tool-qa` | Reference go.mod patterns from these; `go vet`, `go test`, `golangci-lint` |
|
| **Go** | `L6-svrnty.lib-llm`, `L6-svrnty.core-credentials`, `L6-svrnty.core-memory`, `PG-svrnty.tool-qa` | Reference go.mod patterns from these; `go vet`, `go test`, `golangci-lint` |
|
||||||
| **Rust** | `L6-svrnty.core-runtime` (zeroclaw, Tokio) | Mount core-runtime for Rust patterns; `cargo check`, `cargo test`, `cargo clippy` |
|
| **Rust** | `L6-svrnty.core-runtime` (zeroclaw, Tokio) | Mount core-runtime for Rust patterns; `cargo check`, `cargo test`, `cargo clippy` |
|
||||||
| **Python** | None specific — sandcastle generic Claude Code | `ruff check`, `pytest`, `mypy` (if configured in target repo) |
|
| **Python** | `cto-python-toolkit` skill (closes gap inline) — references workspace projects (bte-mcp, svrnty-hermes-webui-plugin, curator/sweep.py, scripts/sot-precommit.py) | `ruff check`, `pytest`, `mypy`; route to `cto-python-toolkit` for prompt + patterns |
|
||||||
| **Angular** | None specific — sandcastle generic Claude Code | `ng lint`, `ng test`, `ng build --configuration production` |
|
| **Angular** | `cto-angular-toolkit` skill (closes gap inline) — anchored to adwright-console (Angular 21 + signals + standalone + gRPC-web) | `ng lint`, `ng test`, `ng build`; route to `cto-angular-toolkit` for prompt + patterns |
|
||||||
| **Bash scripting** | `L5-svrnty.tool-bash-plugin` (cortex-script-v1 standard) | Reference bash-plugin's 9 categories (init/gate/hook/cron/probe/seal/deploy/test/orchestrate); `shellcheck` |
|
| **Bash scripting** | `L5-svrnty.tool-bash-plugin` (cortex-script-v1 standard) | Reference bash-plugin's 9 categories (init/gate/hook/cron/probe/seal/deploy/test/orchestrate); `shellcheck` |
|
||||||
| **Any stack — quality gates** | `PG-svrnty.lib-quality-gates` (48 gates, 7 stacks) | Run as post-sandcastle verification; auto-detect stack from repo |
|
| **Any stack — quality gates** | `PG-svrnty.lib-quality-gates` (48 gates, 7 stacks) | Run as post-sandcastle verification; auto-detect stack from repo |
|
||||||
| **Pattern reference (any stack)** | `L5-svrnty.lib-skills-engineering` (28 patterns) | Mount + reference in prompt when task matches a pattern (saga, events, error handling, CQRS, gRPC) |
|
| **Pattern reference (any stack)** | `L5-svrnty.lib-skills-engineering` (28 patterns) | Mount + reference in prompt when task matches a pattern (saga, events, error handling, CQRS, gRPC) |
|
||||||
|
|||||||
204
skills/cto-angular-toolkit/SKILL.md
Normal file
204
skills/cto-angular-toolkit/SKILL.md
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
---
|
||||||
|
name: cto-angular-toolkit
|
||||||
|
description: "Use when the user mentions 'Angular code task', 'fix bug in Angular repo', 'implement feature in Angular', 'refactor Angular', 'ng', 'ng build', 'ng test', 'angular signal', 'standalone component', 'gRPC-web', 'foblex flow', or the target stack identified by cto-agent is Angular. Encodes Plan B's Angular 21 patterns (signals + standalone components + gRPC-web to .NET CQRS), anchored to the real Adwright console codebase. Closes the Angular stack gap in cto-planb."
|
||||||
|
metadata:
|
||||||
|
version: 0.1.0
|
||||||
|
model: qwen-local/qwen3.6-35b-a3b
|
||||||
|
hermes:
|
||||||
|
requires_toolsets: [terminal, memory_tool]
|
||||||
|
tier: T2
|
||||||
|
status: active
|
||||||
|
owner: jp
|
||||||
|
source: hand
|
||||||
|
last_reviewed: 2026-05-24
|
||||||
|
---
|
||||||
|
|
||||||
|
# CTO Angular Toolkit — Sandcastle Prompt + Plan B Patterns
|
||||||
|
|
||||||
|
> **Scope:** routed-to by `cto-agent` when the target repo stack is Angular. Closes the Angular stack gap documented in `CONTRACT.md §6`. All patterns anchored to **the real Adwright console codebase** — the canonical Plan B Angular reference.
|
||||||
|
|
||||||
|
## When CTO routes here
|
||||||
|
|
||||||
|
Per `skills/cto-agent/SKILL.md` per-stack routing table — Angular row. Triggers:
|
||||||
|
- Target repo contains `angular.json`
|
||||||
|
- `package.json` declares `@angular/core` dependency
|
||||||
|
- Task description mentions Angular explicitly
|
||||||
|
- `cto-agent` analyze step detects Angular as primary stack
|
||||||
|
|
||||||
|
## The canonical Plan B Angular reference
|
||||||
|
|
||||||
|
[`adwright/adwright-console/`](../../../adwright/adwright-console/) — the Adwright console, a federated sibling workspace (registered in workspace CLAUDE.md). Read this codebase before any Angular sandcastle invocation. Pulled facts (verified 2026-05-24):
|
||||||
|
|
||||||
|
| Aspect | Value |
|
||||||
|
|---|---|
|
||||||
|
| Angular version | `^21.2.0` |
|
||||||
|
| Component style | **Standalone** (no NgModule) — `@Component({ imports: [...] })` |
|
||||||
|
| Reactivity | **Signals** — `signal()`, `computed()`, `inject()` |
|
||||||
|
| Routing | `provideRouter(routes)` in `app.config.ts` |
|
||||||
|
| Styles | SCSS (`"inlineStyleLanguage": "scss"`, prefix `app`) |
|
||||||
|
| Build builder | `@angular/build:application` (modern Vite-based, not webpack) |
|
||||||
|
| Backend transport | **gRPC-web** via `@protobuf-ts/grpcweb-transport` → .NET CQRS via `L6-svrnty.lib-cqrs-datasource` |
|
||||||
|
| Generated types | `src/app/gen/<service>/<version>/*` from `.proto` files |
|
||||||
|
| Mock data | `src/app/core/mock-data.service.ts` — dev pattern; mocks signal-typed |
|
||||||
|
| Graph UI lib | `@foblex/flow`, `@foblex/2d`, `@foblex/mediator` (Adwright-specific — pattern not for every project) |
|
||||||
|
|
||||||
|
Key files to study (point sandcastle agent at these):
|
||||||
|
- [`adwright-console/src/app/app.config.ts`](../../../adwright/adwright-console/src/app/app.config.ts) — bootstrap pattern
|
||||||
|
- [`adwright-console/src/app/app.ts`](../../../adwright/adwright-console/src/app/app.ts) — standalone root component w/ signals
|
||||||
|
- [`adwright-console/src/app/core/cycles.service.ts`](../../../adwright/adwright-console/src/app/core/cycles.service.ts) — gRPC-web service w/ status-mapping (proto enums → friendly strings)
|
||||||
|
- [`adwright-console/src/app/core/connections.service.ts`](../../../adwright/adwright-console/src/app/core/connections.service.ts) — service injection pattern
|
||||||
|
- [`adwright-console/src/app/core/mock-data.service.ts`](../../../adwright/adwright-console/src/app/core/mock-data.service.ts) — mock-data signal pattern
|
||||||
|
- [`adwright-console/angular.json`](../../../adwright/adwright-console/angular.json) — schematics defaults (`skipTests: true` per project choice)
|
||||||
|
- [`adwright-console/proxy.conf.json`](../../../adwright/adwright-console/proxy.conf.json) — dev proxy to backend
|
||||||
|
|
||||||
|
## Tooling baseline (always include in sandcastle prompt)
|
||||||
|
|
||||||
|
| Tool | Purpose | Invocation | Required? | Notes from adwright |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| **npm** | Package manager | `npm install` / `npm ci` | YES (adwright uses npm@11.6.2; no pnpm/yarn migration) | Adwright pins `"packageManager": "npm@11.6.2"` in package.json |
|
||||||
|
| **ng build** | Production build | `ng build` | YES — must succeed before PR | Uses `@angular/build:application` builder |
|
||||||
|
| **ng test** | Unit test runner | `ng test --watch=false --browsers=ChromeHeadless` | If tests exist (adwright skips tests by schematic default — match repo choice) | Adwright has `skipTests: true` schematics — only add tests if explicitly scoped |
|
||||||
|
| **ng lint** | Linter (eslint) | `ng lint` | If eslint configured | Add it; default ng new projects don't include it |
|
||||||
|
| **ng serve** | Dev server | `ng serve` (CTO does NOT run this — sandboxed, no port forward) | NO in sandcastle context | Local dev only |
|
||||||
|
|
||||||
|
## Project layout pattern (per adwright-console)
|
||||||
|
|
||||||
|
```
|
||||||
|
<repo>/
|
||||||
|
├── angular.json # workspace config — schematics defaults, builder selection
|
||||||
|
├── package.json # pin Angular major; lock packageManager
|
||||||
|
├── tsconfig.json + tsconfig.app.json + tsconfig.spec.json
|
||||||
|
├── proxy.conf.json # dev proxy to backend (CQRS at :5001 or similar)
|
||||||
|
├── public/ # static assets (served as-is)
|
||||||
|
├── src/
|
||||||
|
│ ├── main.ts # bootstrapApplication(App, appConfig)
|
||||||
|
│ ├── index.html
|
||||||
|
│ ├── styles.scss # global styles
|
||||||
|
│ └── app/
|
||||||
|
│ ├── app.ts # standalone root component (signals)
|
||||||
|
│ ├── app.config.ts # provideRouter + provider list
|
||||||
|
│ ├── app.routes.ts # Routes array (lazy where appropriate)
|
||||||
|
│ ├── app.html / app.scss
|
||||||
|
│ ├── core/ # services — gRPC clients, mock data, models
|
||||||
|
│ │ ├── <name>.service.ts
|
||||||
|
│ │ └── models.ts # shared TS types (do NOT duplicate proto types here)
|
||||||
|
│ └── gen/ # generated proto types — DO NOT edit by hand
|
||||||
|
│ └── <pkg>/<ver>/*.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
Sandcastle prompt MUST tell the agent:
|
||||||
|
- **Use signals + standalone** — no NgModule, no `OnInit` if `computed()` covers it
|
||||||
|
- **Inject via `inject()`**, not constructor injection (modern Angular 16+ pattern)
|
||||||
|
- **Map proto enums → friendly TS string-literal unions** in service layer (per `cycles.service.ts` `CycleStatus` pattern) — UI never sees `CYCLE_STATUS_*` constants
|
||||||
|
- **Mock-data services live in `core/mock-data.service.ts`** during dev; swap to real gRPC client when backend ready
|
||||||
|
- **Never hand-edit `src/app/gen/**`** — regenerate via proto pipeline (see `L6-svrnty.lib-cqrs-datasource` patterns)
|
||||||
|
- **Match existing schematics** — adwright defaults `skipTests: true`, prefix `app`, style `scss`. New components must match.
|
||||||
|
|
||||||
|
## Sandcastle invocation template (Angular)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
SANDCASTLE_REPO="${SANDCASTLE_REPO:-$HOME/workspaces/hermes/sandcastle}"
|
||||||
|
cd "$SANDCASTLE_REPO"
|
||||||
|
npx tsx -e "
|
||||||
|
import { run, claudeCode } from '@ai-hero/sandcastle';
|
||||||
|
import { docker } from '@ai-hero/sandcastle/sandboxes/docker';
|
||||||
|
const result = await run({
|
||||||
|
agent: claudeCode('claude-opus-4-7'),
|
||||||
|
sandbox: docker({
|
||||||
|
image: 'node:22-slim',
|
||||||
|
setup: [
|
||||||
|
'apt-get update && apt-get install -y chromium-browser || true',
|
||||||
|
'cd /workspace && npm ci'
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
promptFile: '${CTO_HOME}/work/${WORK_ID}/prompt.md',
|
||||||
|
cwd: '${TARGET_REPO}',
|
||||||
|
branchStrategy: { type: 'branch', branch: 'cto/${WORK_ID}' },
|
||||||
|
maxIterations: 5,
|
||||||
|
});
|
||||||
|
console.log(JSON.stringify({ commits: result.commits, branch: result.branch }, null, 2));
|
||||||
|
"
|
||||||
|
```
|
||||||
|
|
||||||
|
Prompt file (`prompt.md`) MUST instruct the sandboxed agent to:
|
||||||
|
1. Read `angular.json` — note builder (`@angular/build:application` for v17+; webpack-based for older), schematics defaults, prefix
|
||||||
|
2. Read `package.json` — note Angular major version, packageManager pin
|
||||||
|
3. Reference Adwright patterns at `adwright/adwright-console/src/app/{app.ts, core/cycles.service.ts}` for component + service shape
|
||||||
|
4. Make code changes per the brief — match existing standalone + signals + inject() patterns
|
||||||
|
5. Run `ng lint` if configured — must pass
|
||||||
|
6. Run `ng build` — must succeed (this catches type errors + template errors)
|
||||||
|
7. Run `ng test --watch=false --browsers=ChromeHeadless` if tests exist
|
||||||
|
8. Commit + report
|
||||||
|
|
||||||
|
## Post-run quality gates (mount `PG-svrnty.lib-quality-gates` if available)
|
||||||
|
|
||||||
|
After sandcastle completes, run quality gates against the diff:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
QG=/home/svrnty/workspaces/cortex/PG-svrnty.lib-quality-gates
|
||||||
|
[ -d "$QG" ] && "$QG/bin/run-gates" --stack typescript --repo "${TARGET_REPO}" --branch "cto/${WORK_ID}"
|
||||||
|
```
|
||||||
|
|
||||||
|
The lib-quality-gates TypeScript/Angular suite (per `CORTEX-TOOLING.md`) covers:
|
||||||
|
- Strict TypeScript config validation (`strict: true`, `noImplicitAny`, etc.)
|
||||||
|
- Bundle size budgets (`angular.json → architect.build.options.budgets`)
|
||||||
|
- Accessibility lint (axe / Angular ESLint a11y rules)
|
||||||
|
- Dep vulns (`npm audit --production`)
|
||||||
|
|
||||||
|
If gates fail: re-prompt sandcastle with violations, max 3 iterations, then escalate to JP.
|
||||||
|
|
||||||
|
## DESIGN.md compliance (Angular UI + Stitch consumers)
|
||||||
|
|
||||||
|
Per `CONTRACT.md §7`, when CTO sandcastle-orchestrates Angular UI work AND the output feeds DESIGN.md-aware tools (Stitch, others), components MUST conform to the 8-property DESIGN.md subset: `backgroundColor`, `textColor`, `typography`, `rounded`, `padding`, `size`, `height`, `width`.
|
||||||
|
|
||||||
|
Workflow:
|
||||||
|
1. CTO ensures sandcastle agent emits components compatible with the 8-property contract
|
||||||
|
2. Post-build, run `pi-bte-plugin design-md-exporter` to emit `BRAND-DESIGN.md` from the brand's DTCG token set
|
||||||
|
3. Validate: `npx --yes @google/design.md@latest lint BRAND-DESIGN.md`
|
||||||
|
4. If validation fails: re-prompt sandcastle with the lint error + the 8-property contract
|
||||||
|
|
||||||
|
Concrete adwright opportunity: the `@foblex/flow` graph nodes could expose their styles via DESIGN.md tokens (currently they don't — that's a future task scope, not implicit in every Adwright task).
|
||||||
|
|
||||||
|
## Worked example — add a route to adwright-console
|
||||||
|
|
||||||
|
Task: "Add a `/profiles` route that lists Hermes profile distributions (from svrnty-hermes-webui-plugin's `/api/profile-catalog`)."
|
||||||
|
|
||||||
|
Sandcastle prompt would:
|
||||||
|
1. Mount `/home/svrnty/workspaces/hermes/adwright/adwright-console/` as cwd
|
||||||
|
2. Reference `src/app/core/cycles.service.ts` as the gRPC-service pattern — but note: this new endpoint is REST/JSON (svrnty-plugin route), not gRPC. So use `HttpClient` (`provideHttpClient()` added to `app.config.ts`) instead of gRPC-web transport.
|
||||||
|
3. Generate component: `ng generate component features/profiles --standalone --skip-tests` (matches adwright defaults)
|
||||||
|
4. Add route in `app.routes.ts`: `{ path: 'profiles', loadComponent: () => import('./features/profiles/profiles').then(m => m.Profiles) }`
|
||||||
|
5. Inject `HttpClient` via `inject(HttpClient)`; signal-typed response
|
||||||
|
6. Run `ng build`
|
||||||
|
7. Commit on branch `cto/<work-id>`, open PR
|
||||||
|
|
||||||
|
## Anti-patterns (sandcastle prompt MUST forbid)
|
||||||
|
|
||||||
|
- NgModule (`@NgModule({...})`) — use standalone components only (Angular 21+ pattern)
|
||||||
|
- Constructor injection (`constructor(private svc: MyService)`) — use `inject()`
|
||||||
|
- `BehaviorSubject` for UI state — use `signal()` (RxJS only for stream-of-events, not state)
|
||||||
|
- Hand-editing `src/app/gen/**` — regenerate from proto sources
|
||||||
|
- Adding tests when repo schematics declare `skipTests: true` — match the repo choice; only add tests if task scope explicit
|
||||||
|
- Bumping Angular major version (e.g., 21 → 22) without JP approval — major framework bumps = JP decision
|
||||||
|
- Adding heavy UI libs (Material/PrimeNG/etc.) without explicit task scope — Adwright is intentionally lean
|
||||||
|
- Editing `proxy.conf.json` to bypass auth or hit prod backends — dev-only file
|
||||||
|
- `<div [innerHTML]="..."` without `DomSanitizer` — XSS risk
|
||||||
|
|
||||||
|
## Stack gap roadmap
|
||||||
|
|
||||||
|
This skill closes the Angular gap inline. The future path:
|
||||||
|
1. v0.x: this inline-pattern skill (CURRENT) — anchored to adwright-console
|
||||||
|
2. v1.x: extract canonical patterns into `cortex/L6-svrnty.lib-angular-framework` (deferred — adwright is the only Angular consumer today)
|
||||||
|
3. When extracted: replace skill body with `mount cortex/L6-svrnty.lib-angular-framework`
|
||||||
|
|
||||||
|
Until then, **adwright-console is the framework reference**. If adwright pattern conflicts with this doc, adwright wins — update this doc to match.
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- [`../cto-agent/SKILL.md`](../cto-agent/SKILL.md) — orchestrator that routes here
|
||||||
|
- [`../../CONTRACT.md`](../../CONTRACT.md) §6 — Angular stack disclosure (gap status); §7 — DESIGN.md compliance
|
||||||
|
- [`../../../sot/06-REGISTRY/CORTEX-TOOLING.md`](../../../sot/06-REGISTRY/CORTEX-TOOLING.md) — confirms Angular has no dedicated cortex/ lib (yet)
|
||||||
|
- [`../../../sot/03-PROTOCOLS/ADWRIGHT-PANEL-PRD.md`](../../../sot/03-PROTOCOLS/ADWRIGHT-PANEL-PRD.md) — Adwright panel inside hermes-webui PRD
|
||||||
|
- [`../../../sot/03-PROTOCOLS/ADWRIGHT-CREATIVE-EXTRACTION-PRD.md`](../../../sot/03-PROTOCOLS/ADWRIGHT-CREATIVE-EXTRACTION-PRD.md) — Adwright creative extraction PRD
|
||||||
|
- [`../cto-python-toolkit/SKILL.md`](../cto-python-toolkit/SKILL.md) — sibling skill closing Python gap
|
||||||
|
- [`../../../adwright/adwright-console/`](../../../adwright/adwright-console/) — the canonical Plan B Angular reference codebase
|
||||||
185
skills/cto-python-toolkit/SKILL.md
Normal file
185
skills/cto-python-toolkit/SKILL.md
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
---
|
||||||
|
name: cto-python-toolkit
|
||||||
|
description: "Use when the user mentions 'Python code task', 'fix bug in Python repo', 'implement feature in Python', 'refactor Python', 'pytest', 'ruff', 'mypy', 'uv', 'python-task', or the target stack identified by cto-agent is Python. Encodes Python best-practice patterns for sandcastle invocations: tooling (ruff/pytest/mypy/uv), project layout, post-run quality-gate routing. Closes the Python stack gap in cto-planb (no dedicated cortex/ Python framework lib yet — this skill provides the patterns inline, anchored to real workspace Python projects)."
|
||||||
|
metadata:
|
||||||
|
version: 0.1.0
|
||||||
|
model: qwen-local/qwen3.6-35b-a3b
|
||||||
|
hermes:
|
||||||
|
requires_toolsets: [terminal, memory_tool]
|
||||||
|
tier: T2
|
||||||
|
status: active
|
||||||
|
owner: jp
|
||||||
|
source: hand
|
||||||
|
last_reviewed: 2026-05-24
|
||||||
|
---
|
||||||
|
|
||||||
|
# CTO Python Toolkit — Sandcastle Prompt + Quality Patterns
|
||||||
|
|
||||||
|
> **Scope:** routed-to by `cto-agent` when the target repo stack is Python. Closes the Python stack gap documented in `CONTRACT.md §6` (no cortex/ Python framework lib exists; this skill provides the patterns inline). All patterns anchored to **real Python projects in this workspace** — no hypothetical examples.
|
||||||
|
|
||||||
|
## When CTO routes here
|
||||||
|
|
||||||
|
Per `skills/cto-agent/SKILL.md` per-stack routing table — Python row. Triggers:
|
||||||
|
- Target repo contains `pyproject.toml`, `setup.py`, `requirements*.txt`, or `*.py` files at root
|
||||||
|
- Task description mentions Python explicitly
|
||||||
|
- `cto-agent` analyze step detects Python as primary stack
|
||||||
|
|
||||||
|
## Reference Python projects in this workspace (study these patterns)
|
||||||
|
|
||||||
|
| Repo | Pattern shown | What to copy |
|
||||||
|
|---|---|---|
|
||||||
|
| [`scripts/sot-precommit.py`](../../../scripts/sot-precommit.py) | Single-file CLI w/ stdlib + 1 dep (pyyaml); `pathlib`-first; `subprocess.check_output` for git; `re` for parsing; type hints (`Optional[str]`); function-level docstrings | Single-file tools, git-integration scripts, validators |
|
||||||
|
| [`bte-mcp/server.py`](../../../bte-mcp/server.py) + [`bte-mcp/bte_core.py`](../../../bte-mcp/bte_core.py) | FastMCP server (`mcp.server.fastmcp`); decorator-based tool registration (`@mcp.tool()`); thin transport (server.py) + business logic (bte_core.py) split; env-driven config | New MCP servers, thin stateless proxies |
|
||||||
|
| [`svrnty-hermes-webui-plugin/`](../../../svrnty-hermes-webui-plugin/) | Modern PEP 621 pyproject; `[tool.pytest.ini_options]` w/ testpaths + python_files; setuptools packages.find; Flask-style routes (`routes/*.py`); README + CHANGELOG + CLAUDE.md per repo | Packaged libraries, web plugins, multi-route Python apps |
|
||||||
|
| [`curator/sweep.py`](../../../curator/sweep.py) | Long-running script w/ mode flags (`--validate-only`/`--index-only`/`--dry-run`); `from __future__ import annotations`; stdlib-heavy (no extra deps); subprocess to other Python scripts | Long-running tasks, idempotent sweeps, dry-run patterns |
|
||||||
|
| [`hermes-agent/`](../../../hermes-agent/) | **READ-ONLY** upstream — DO NOT modify or use as edit target. Study only as constraint reference (Hermes core API surfaces) | Reference only — never modify |
|
||||||
|
| [`cortex/L3-svrnty.agents-voice`](../../../../cortex/L3-svrnty.agents-voice), `agents-training`, `agents-trust` | Multi-package L3 agents w/ pyproject; Python-side svrnty stack reference | Agent libs, ML-adjacent agents |
|
||||||
|
|
||||||
|
When the sandcastle agent needs an exemplar, point it at the closest match above. Example sandcastle prompt fragment:
|
||||||
|
|
||||||
|
> "For project layout + pyproject + pytest config, follow `svrnty-hermes-webui-plugin/pyproject.toml` as the canonical Plan B Python pattern. For single-file CLI scripts, follow `scripts/sot-precommit.py`."
|
||||||
|
|
||||||
|
## Tooling baseline (always include in sandcastle prompt)
|
||||||
|
|
||||||
|
| Tool | Purpose | Invocation | Required? | Real example |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| **uv** | Package + venv manager | `uv sync` / `uv pip install` | Preferred (faster than pip) | bte-mcp uses pip + requirements.txt (legacy); migrate new projects to uv + pyproject |
|
||||||
|
| **ruff** | Linter + formatter | `ruff check .` / `ruff format .` | YES — fail PR if violations | Add to svrnty-hermes-webui-plugin's pyproject (currently uses default ruff config) |
|
||||||
|
| **pytest** | Test runner | `pytest` / `pytest -x` (fail-fast) | YES if tests exist | svrnty-hermes-webui-plugin has `[tool.pytest.ini_options]` block — use that shape |
|
||||||
|
| **mypy** | Static type checker | `mypy <pkg>` | If `mypy` configured in pyproject.toml | scripts/sot-precommit.py uses `Optional[str]` hints throughout — type-hint public APIs |
|
||||||
|
| **pip-audit** | Vuln scan | `pip-audit` | Recommended for dep changes | not yet in any workspace project — first task to add can be the reference |
|
||||||
|
|
||||||
|
## Project layout patterns (encode in prompt)
|
||||||
|
|
||||||
|
Two valid Plan B layouts (match the existing repo style — don't migrate without explicit task):
|
||||||
|
|
||||||
|
**Layout A — single-file CLI** (per `scripts/sot-precommit.py`):
|
||||||
|
```
|
||||||
|
<repo>/
|
||||||
|
├── tool-name.py # entry point, stdlib + ≤1 dep
|
||||||
|
├── pyproject.toml # PEP 621 if shipping; omit if just a script
|
||||||
|
└── README.md
|
||||||
|
```
|
||||||
|
|
||||||
|
**Layout B — packaged lib + routes** (per `svrnty-hermes-webui-plugin/`):
|
||||||
|
```
|
||||||
|
<repo>/
|
||||||
|
├── pyproject.toml # PEP 621 / setuptools; [tool.pytest.ini_options]
|
||||||
|
├── <pkg_name>/__init__.py # main package (flat-layout used here)
|
||||||
|
├── routes/ # if web/plugin: sub-modules per route group
|
||||||
|
│ └── *.py
|
||||||
|
├── tests/test_*.py # pytest discovery
|
||||||
|
├── CHANGELOG.md
|
||||||
|
├── CLAUDE.md # repo-local Claude context (Hermes convention)
|
||||||
|
└── README.md
|
||||||
|
```
|
||||||
|
|
||||||
|
**Layout C — modular service** (per `bte-mcp/`):
|
||||||
|
```
|
||||||
|
<repo>/
|
||||||
|
├── server.py # thin transport (FastMCP / FastAPI / Flask)
|
||||||
|
├── <name>_core.py # business logic (importable, testable)
|
||||||
|
├── requirements.txt OR pyproject.toml
|
||||||
|
├── .env.example
|
||||||
|
└── README.md
|
||||||
|
```
|
||||||
|
|
||||||
|
Sandcastle prompt MUST tell the agent:
|
||||||
|
- **Match existing layout** — do NOT migrate src-layout↔flat-layout mid-task
|
||||||
|
- Type-hint public APIs (mypy will gate)
|
||||||
|
- Use **pytest fixtures**, not unittest-style setUp/tearDown
|
||||||
|
- Async code: prefer `asyncio` stdlib + `pytest-asyncio` for tests
|
||||||
|
- No `print()` debugging in committed code — use `logging` module (or stderr for CLI tools — see `sot-precommit.py` for `print(..., file=sys.stderr)` pattern)
|
||||||
|
|
||||||
|
## Sandcastle invocation template (Python)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
SANDCASTLE_REPO="${SANDCASTLE_REPO:-$HOME/workspaces/hermes/sandcastle}"
|
||||||
|
cd "$SANDCASTLE_REPO"
|
||||||
|
npx tsx -e "
|
||||||
|
import { run, claudeCode } from '@ai-hero/sandcastle';
|
||||||
|
import { docker } from '@ai-hero/sandcastle/sandboxes/docker';
|
||||||
|
const result = await run({
|
||||||
|
agent: claudeCode('claude-opus-4-7'),
|
||||||
|
sandbox: docker({
|
||||||
|
image: 'python:3.12-slim',
|
||||||
|
setup: [
|
||||||
|
'pip install uv',
|
||||||
|
'cd /workspace && (uv sync 2>/dev/null || pip install -e \".[dev]\" 2>/dev/null || pip install -r requirements-dev.txt 2>/dev/null || pip install -r requirements.txt)'
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
promptFile: '${CTO_HOME}/work/${WORK_ID}/prompt.md',
|
||||||
|
cwd: '${TARGET_REPO}',
|
||||||
|
branchStrategy: { type: 'branch', branch: 'cto/${WORK_ID}' },
|
||||||
|
maxIterations: 5,
|
||||||
|
});
|
||||||
|
console.log(JSON.stringify({ commits: result.commits, branch: result.branch }, null, 2));
|
||||||
|
"
|
||||||
|
```
|
||||||
|
|
||||||
|
Prompt file (`prompt.md`) MUST instruct the sandboxed agent to:
|
||||||
|
1. Read `pyproject.toml` (or fall back to `setup.py` / `requirements*.txt`) — identify dependency manager
|
||||||
|
2. Identify layout (A/B/C above) — match it
|
||||||
|
3. Make code changes per the brief
|
||||||
|
4. Run `ruff check . && ruff format --check .` — must pass
|
||||||
|
5. Run `pytest` — must pass (if tests exist; check `[tool.pytest.ini_options].testpaths`)
|
||||||
|
6. Run `mypy <pkg>` — must pass (if mypy configured)
|
||||||
|
7. Commit + report
|
||||||
|
|
||||||
|
## Post-run quality gates (mount `PG-svrnty.lib-quality-gates` if available)
|
||||||
|
|
||||||
|
After sandcastle completes, run quality gates against the diff:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
QG=/home/svrnty/workspaces/cortex/PG-svrnty.lib-quality-gates
|
||||||
|
[ -d "$QG" ] && "$QG/bin/run-gates" --stack python --repo "${TARGET_REPO}" --branch "cto/${WORK_ID}"
|
||||||
|
```
|
||||||
|
|
||||||
|
The lib-quality-gates Python suite covers (per `CORTEX-TOOLING.md`):
|
||||||
|
- import order (isort-compatible)
|
||||||
|
- docstring coverage (interrogate)
|
||||||
|
- complexity (radon CC ≤ 10)
|
||||||
|
- security (bandit)
|
||||||
|
- dependency vulns (safety / pip-audit)
|
||||||
|
|
||||||
|
If gates fail: re-prompt sandcastle with the gate violations, max 3 iterations, then escalate to JP.
|
||||||
|
|
||||||
|
## Worked example — add a route to svrnty-hermes-webui-plugin
|
||||||
|
|
||||||
|
Task: "Add a route `/api/profile-catalog` that returns parsed PROFILE-CATALOG.md as JSON."
|
||||||
|
|
||||||
|
Sandcastle prompt would:
|
||||||
|
1. Mount `/home/svrnty/workspaces/hermes/svrnty-hermes-webui-plugin/` as cwd
|
||||||
|
2. Reference existing `routes/transcribe.py` and `routes/vault_status.py` as the route pattern
|
||||||
|
3. Add `routes/profile_catalog.py` with FastAPI/Flask handler (match existing style — inspect first)
|
||||||
|
4. Wire into `routes/__init__.py`
|
||||||
|
5. Add `tests/test_profile_catalog.py`
|
||||||
|
6. Run `pytest tests/test_profile_catalog.py` to verify
|
||||||
|
7. Run `ruff check routes/profile_catalog.py tests/test_profile_catalog.py`
|
||||||
|
8. Commit on branch `cto/<work-id>`, open PR
|
||||||
|
|
||||||
|
## Anti-patterns (sandcastle prompt MUST forbid)
|
||||||
|
|
||||||
|
- `pip install` without pinning (use `uv pip install <pkg>==<version>` or update lockfile)
|
||||||
|
- Bare `except:` clauses — must specify exception class (see `sot-precommit.py:git_read_staged` for correct catch)
|
||||||
|
- Mutable default arguments (`def f(x=[]):`) — use `None` sentinel + check
|
||||||
|
- `time.sleep()` in tests (use `pytest-asyncio` + `asyncio.sleep` or `freezegun`)
|
||||||
|
- Editing `.python-version` without JP approval (project Python upgrade = JP decision)
|
||||||
|
- Adding ML/AI deps (torch, transformers, etc.) without explicit task scope — they are heavy
|
||||||
|
- Modifying `hermes-agent/*.py` — workspace hard rule (read-only upstream)
|
||||||
|
|
||||||
|
## Stack gap roadmap
|
||||||
|
|
||||||
|
This skill closes the Python gap inline. The future path (per workspace CLAUDE.md):
|
||||||
|
1. v0.x: this inline-pattern skill (CURRENT)
|
||||||
|
2. v1.x: extract canonical patterns into `cortex/L6-svrnty.lib-python-framework` (deferred — not yet justified by usage)
|
||||||
|
3. When extracted: replace this skill body with `mount cortex/L6-svrnty.lib-python-framework` + the routing table moves there
|
||||||
|
|
||||||
|
Until v1.x, this file IS the framework reference.
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- [`../cto-agent/SKILL.md`](../cto-agent/SKILL.md) — orchestrator that routes here
|
||||||
|
- [`../../CONTRACT.md`](../../CONTRACT.md) §6 — Python stack disclosure (gap status)
|
||||||
|
- [`../../../sot/06-REGISTRY/CORTEX-TOOLING.md`](../../../sot/06-REGISTRY/CORTEX-TOOLING.md) — confirms Python has no dedicated cortex/ lib (yet)
|
||||||
|
- [`../cto-angular-toolkit/SKILL.md`](../cto-angular-toolkit/SKILL.md) — sibling skill closing Angular gap
|
||||||
Loading…
Reference in New Issue
Block a user