pi-rolecast 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +260 -0
  3. package/SKILL.md +89 -0
  4. package/dist/extension.d.ts +25 -0
  5. package/dist/extension.js +287 -0
  6. package/examples/rust/README.md +22 -0
  7. package/examples/rust/profile.yaml +51 -0
  8. package/package.json +71 -0
  9. package/references/dispatch-model-semantics.md +110 -0
  10. package/references/gate-runner-usage.md +19 -0
  11. package/references/migration-from-rust-agent-workflow.md +107 -0
  12. package/references/profile-schema.md +66 -0
  13. package/references/registry-resolution.md +14 -0
  14. package/references/scaffolder-usage.md +27 -0
  15. package/references/sync-settings-usage.md +67 -0
  16. package/registry/aliases.yaml +38 -0
  17. package/registry/built_in.yaml +42 -0
  18. package/requirements.txt +2 -0
  19. package/role-packs/coding/coding-architect.md +33 -0
  20. package/role-packs/coding/coding-auditor.md +31 -0
  21. package/role-packs/coding/coding-canary.md +31 -0
  22. package/role-packs/coding/coding-docs.md +32 -0
  23. package/role-packs/coding/coding-implementer.md +33 -0
  24. package/role-packs/coding/coding-mapper.md +31 -0
  25. package/role-packs/coding/coding-orchestrator.md +28 -0
  26. package/role-packs/coding/coding-planner.md +31 -0
  27. package/role-packs/coding/coding-profiler.md +31 -0
  28. package/role-packs/coding/coding-reviewer.md +32 -0
  29. package/role-packs/coding/coding-tester.md +32 -0
  30. package/scripts/gate_runner.py +155 -0
  31. package/scripts/install.sh +120 -0
  32. package/scripts/profile_loader.py +633 -0
  33. package/scripts/scaffolder.py +289 -0
  34. package/scripts/sync_settings.py +362 -0
  35. package/templates/blank.yaml +13 -0
  36. package/templates/go.yaml +44 -0
  37. package/templates/python.yaml +46 -0
  38. package/templates/rust.yaml +49 -0
  39. package/templates/typescript.yaml +46 -0
@@ -0,0 +1,22 @@
1
+ # Rust example profile (pi-rolecast v0.2.0)
2
+
3
+ This directory contains the reference profile for the `coding` group of
4
+ pi-rolecast v0.2.0. It reproduces the routing decisions of the original
5
+ `rust-agent-workflow` skill (pre-2026-10-03), adapted to the new
6
+ grouped-role schema.
7
+
8
+ ## Purpose
9
+
10
+ Users should:
11
+
12
+ 1. Run `scaffolder init --template rust` in their project.
13
+ 2. Diff the generated profile against `examples/rust/profile.yaml`.
14
+ 3. If differences exist, decide deliberately which is canonical.
15
+
16
+ This file is the **ground truth** for "what the coding group does for Rust projects". If your scaffolder-generated profile diverges, file an issue.
17
+
18
+ ## What this is NOT
19
+
20
+ This is not a one-click migration from `rust-agent-workflow`. See
21
+ `references/migration-from-rust-agent-workflow.md` for the v0.1.x → v0.2.0
22
+ upgrade path.
@@ -0,0 +1,51 @@
1
+ # Reference profile reproducing today's rust-agent-workflow routing,
2
+ # updated for pi-rolecast v0.2.0 (grouped roles, hyphen-prefixed names).
3
+ # Generated manually from the old SKILL.md; this is the ground truth
4
+ # users cross-check their scaffolder-generated profile against.
5
+
6
+ framework_version: 0.2.0
7
+ name: rust-rolecast-example
8
+ description: |
9
+ Reference Rust profile preserving the routing decisions of the original
10
+ rust-agent-workflow skill, updated to the v0.2.0 grouped-role schema.
11
+ Use scaffolder init --template rust in your project to generate a
12
+ similar profile; this file is the canonical reference for cross-checking.
13
+
14
+ workflow:
15
+ role_groups: [coding]
16
+
17
+ gates:
18
+ compile:
19
+ commands: [cargo check --message-format short --all-targets]
20
+ timeout: 300
21
+ lint:
22
+ commands: [cargo clippy -- -D warnings]
23
+ timeout: 300
24
+ test:
25
+ commands: [cargo test]
26
+ timeout: 900
27
+
28
+ bindings:
29
+ coding-architect: {alias: opus-thinking-medium, channels: [official]}
30
+ coding-planner: {alias: deepseek-verifiable, channels: [official]}
31
+ coding-implementer: {alias: deepseek-verifiable, channels: [official]}
32
+ coding-tester: {alias: deepseek-verifiable, channels: [official]}
33
+ coding-reviewer: {alias: gpt-judgment-high, channels: [official, relay-default]}
34
+ coding-mapper: {alias: deepseek-verifiable, channels: [official]}
35
+ coding-profiler: {alias: deepseek-verifiable, channels: [official]}
36
+ coding-auditor: {alias: opus-thinking-high, channels: [official]}
37
+ coding-canary: {alias: minimax-fast, channels: [official]}
38
+ coding-docs: {alias: minimax-medium, channels: [official]}
39
+ coding-orchestrator: {alias: gpt-judgment-medium, channels: [official, relay-default]}
40
+
41
+ non_negotiables:
42
+ forbidden_patterns:
43
+ - pattern: '#\[allow\('
44
+ message: "never silence a diagnostic with #[allow(...)]"
45
+ - pattern: '\.unwrap\(\)'
46
+ message: "no bare .unwrap() — handle the Result"
47
+
48
+ escalation:
49
+ max_attempts: 2
50
+ on_permanent_failure: stop
51
+ preserve_logs: true
package/package.json ADDED
@@ -0,0 +1,71 @@
1
+ {
2
+ "name": "pi-rolecast",
3
+ "version": "0.2.0",
4
+ "description": "Multi-agent role framework for Pi. Groups of specialist agents (coding, video, etc.) bound to per-role models, dispatched via pi-subagents. Profile-driven, gate-verified, language-agnostic.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "author": {
8
+ "name": "rootazero",
9
+ "email": "zouguojunx@gmail.com"
10
+ },
11
+ "homepage": "https://github.com/rootazero/pi-rolecast#readme",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/rootazero/pi-rolecast.git"
15
+ },
16
+ "bugs": {
17
+ "url": "https://github.com/rootazero/pi-rolecast/issues"
18
+ },
19
+ "publishConfig": {
20
+ "access": "public"
21
+ },
22
+ "main": "./dist/extension.js",
23
+ "types": "./dist/extension.d.ts",
24
+ "files": [
25
+ "dist/",
26
+ "scripts/*.py",
27
+ "scripts/*.sh",
28
+ "!scripts/__pycache__/",
29
+ "!scripts/**/__pycache__/",
30
+ "!scripts/*.pyc",
31
+ "role-packs/",
32
+ "registry/",
33
+ "templates/",
34
+ "examples/",
35
+ "references/",
36
+ "SKILL.md",
37
+ "README.md",
38
+ "requirements.txt"
39
+ ],
40
+ "scripts": {
41
+ "build": "tsc",
42
+ "typecheck": "tsc --noEmit",
43
+ "clean": "rm -rf dist",
44
+ "test": "tsx --test tests/unit/test_extension.ts",
45
+ "prepublishOnly": "npm run typecheck && npm run build && npm test"
46
+ },
47
+ "keywords": [
48
+ "pi-package",
49
+ "pi",
50
+ "pi-extension",
51
+ "agents",
52
+ "roles",
53
+ "rolecast",
54
+ "multi-agent",
55
+ "scaffolder",
56
+ "gate-runner"
57
+ ],
58
+ "peerDependencies": {
59
+ "@earendil-works/pi-ai": ">=0.84.0",
60
+ "@earendil-works/pi-coding-agent": ">=0.84.0",
61
+ "@earendil-works/pi-tui": ">=0.84.0"
62
+ },
63
+ "pi": {
64
+ "extensions": [
65
+ "./dist/extension.js"
66
+ ]
67
+ },
68
+ "devDependencies": {
69
+ "tsx": "^4.23.15"
70
+ }
71
+ }
@@ -0,0 +1,110 @@
1
+ ---
2
+ title: Dispatch model semantics
3
+ description: How role model bindings flow through pi-subagents dispatch paths
4
+ ---
5
+
6
+ # Dispatch model semantics
7
+
8
+ `sync_settings.py` writes project-local agent files at `<cwd>/.pi/agents/<role>.md`
9
+ with a `model: provider/modelId` frontmatter field for every profile binding.
10
+ This doc explains how that field is consumed on each dispatch path.
11
+
12
+ ## The three dispatch paths in pi-subagents
13
+
14
+ ### Path 1: Plain text prompt (no `@` mention)
15
+
16
+ - User types `design the API` or `/architect design the API` directly
17
+ - pi checks for a registered slash command — `/architect` is **not** registered
18
+ (only `/agents` is, by pi-subagents itself)
19
+ - Text falls through to the `input` event and reaches the **main LLM**
20
+ - The main LLM may decide to call the `agent` tool with
21
+ `subagent_type: "architect"`, but that is its choice — not guaranteed
22
+ - The main LLM uses the session's default model
23
+
24
+ > **Pitfall.** Typing `/architect design the API` does *not* dispatch a
25
+ > subagent. It is just text the main LLM sees. To get a guaranteed
26
+ > subagent dispatch you must use either Path 2 (`@handle` syntax) or Path 3
27
+ > (the `agent` tool).
28
+
29
+ ### Path 2: `@handle` mention syntax (Claude Code style)
30
+
31
+ - User types `@architect design the API`
32
+ - pi-subagents' `input` handler (`dist/index.js` ≈ line 800) intercepts the
33
+ text. The mention regex is `/^@([\w-]+)\s+([\s\S]+)$/`
34
+ - pi-subagents dispatches **synchronously** to a subagent with the agent
35
+ file's `model:` and `thinking:` fields
36
+ - The subagent session is **fresh**; the parent's model does not change
37
+
38
+ > **Quirk.** This path requires `@` (not `/`) and at least one space before
39
+ > the message. `@architect` with no message is left alone.
40
+
41
+ ### Path 3: `agent` tool / `SubagentWorkflow`
42
+
43
+ - `Agent({ subagent_type: 'architect' })` or
44
+ `SubagentWorkflow({ agentType: 'architect' })` — model-driven dispatch
45
+ - The new subagent session uses the agent file's `model:` and `thinking:`
46
+ - `resolveDefaultModel` (`@tintinweb/pi-subagents/dist/agent-runner.js`
47
+ ≈ line 316) parses `provider/modelId` and resolves via the model registry
48
+
49
+ ```js
50
+ // Agent tool example (subagent_type matches the role name)
51
+ await parallel([
52
+ () => agent("design the API", { label: 'architect', agentType: 'architect' }),
53
+ () => agent("implement it", { label: 'impl', agentType: 'implementer' }),
54
+ ])
55
+
56
+ // SubagentWorkflow
57
+ await agent('coordinate the build', { agentType: 'orchestrator' })
58
+ ```
59
+
60
+ ## Why `provider/modelId` format
61
+
62
+ `resolveDefaultModel` does:
63
+
64
+ ```js
65
+ if (configModel) {
66
+ const slashIdx = configModel.indexOf("/");
67
+ if (slashIdx !== -1) {
68
+ const provider = configModel.slice(0, slashIdx);
69
+ const modelId = configModel.slice(slashIdx + 1);
70
+ // resolve in registry.find(provider, modelId)
71
+ }
72
+ }
73
+ return parentModel; // silent fallback
74
+ ```
75
+
76
+ A plain `model: MiniMax-M3` (no slash) is rejected. The runner silently
77
+ falls back to the parent session's model — which is usually the default
78
+ model set at startup.
79
+
80
+ `sync_settings.py` therefore rewrites every binding to
81
+ `provider/modelId`. The mapping lives in the script as `VENDOR_TO_PROVIDER`:
82
+
83
+ | registry `vendor` | pi provider key | example model binding |
84
+ | ----------------- | ----------------- | ----------------------------- |
85
+ | `minimax` | `minimax-cn` | `minimax-cn/MiniMax-M3` |
86
+ | `deepseek` | `deepseek` | `deepseek/deepseek-flash` |
87
+ | `openai` | `openai-codex` | `openai-codex/gpt-6.1-sol` |
88
+ | `moonshotai` | `kimi-coding` | `kimi-coding/kimi-for-coding` |
89
+ | `typesafe` | `typesafe` | `typesafe/jev-latest` |
90
+
91
+ If your registry uses a vendor not in the table, add it to the script's
92
+ `VENDOR_TO_PROVIDER` and re-run `sync_settings.py`.
93
+
94
+ ## Summary
95
+
96
+ | Path | Dispatch mechanism | Binding honoured? | Caveats |
97
+ | ------------------- | ------------------ | ----------------- | -------------------------------- |
98
+ | Plain text | main LLM | no | model is session default |
99
+ | `@handle` mention | sync subagent | **yes** | needs `@` + space + message |
100
+ | `agent` tool | sync subagent | **yes** | model-driven, needs no @ syntax |
101
+ | `SubagentWorkflow` | subagent pipeline | **yes** | orchestrator pattern |
102
+
103
+ ## Practical usage
104
+
105
+ For interactive `pi` sessions, the cleanest invocation is the `@handle`
106
+ mention. For automation and subagent pipelines, use `agent` /
107
+ `SubagentWorkflow` with `subagent_type` / `agentType`.
108
+
109
+ The `sync_settings.py` output is the same for both — `provider/modelId` is
110
+ all that matters.
@@ -0,0 +1,19 @@
1
+ # Gate runner usage (pi-rolecast v0.2.0)
2
+
3
+ ```bash
4
+ python3 $SKILL_ROOT/scripts/gate_runner.py \
5
+ --profile .pi/rolecast.yaml \
6
+ [--phase NAME | --phase all] \
7
+ [--log-dir DIR] \
8
+ [--framework-root DIR]
9
+ ```
10
+
11
+ The `--profile` flag also accepts the legacy `.pi/agent-workflow.yaml` filename for one release.
12
+
13
+ Exit codes: `0` (all phases pass), `1` (phase failed after retries), `2` (config error).
14
+
15
+ Phases run in declared order. Default escalation: `max_attempts=2`, `on_permanent_failure=stop`, `preserve_logs=true`.
16
+
17
+ Logs written to `<log-dir>/<timestamp>/<phase>-attempt<N>.log` plus `summary.json` on stdout. Default log directory is `.pi/rolecast-logs/` (was `.pi/agent-workflow-logs/` in v0.1.x).
18
+
19
+ Non-negotiables are NOT enforced by gate-runner; the reviewer agent checks them at diff-review time.
@@ -0,0 +1,107 @@
1
+ # Migration from v0.1.x (pi-agent-workflow) to v0.2.0 (pi-rolecast)
2
+
3
+ v0.2.0 is a **breaking release**. The package is renamed from `@rootazero/pi-agent-workflow` (scoped) to `pi-rolecast` (unscoped), roles are now grouped, and role names are hyphen-prefixed.
4
+
5
+ ## Summary of changes
6
+
7
+ | Area | v0.1.x | v0.2.0 |
8
+ |---|---|---|
9
+ | npm package | `@rootazero/pi-agent-workflow` | `pi-rolecast` |
10
+ | Profile filename | `.pi/agent-workflow.yaml` | `.pi/rolecast.yaml` (legacy still recognised) |
11
+ | Role source dir | `agents/<role>.md` | `role-packs/<group>/<role>.md` |
12
+ | Role name format | `architect` | `coding-architect` (full prefixed) |
13
+ | Role scope | All roles are coding | Groups: coding, video, research, ... (future) |
14
+ | Profile field `workflow.role_groups` | (did not exist) | required top-level field |
15
+ | Dispatch mention | `@architect` | `@coding-architect` |
16
+ | Agent tool subagent_type | `architect` | `coding-architect` |
17
+ | Registry user-global dir | `~/.pi/agent-workflow/` | `~/.pi/rolecast/` |
18
+ | Log directory | `.pi/agent-workflow-logs/` | `.pi/rolecast-logs/` |
19
+
20
+ ## Step-by-step migration
21
+
22
+ ```bash
23
+ # 1. Uninstall the old package (keeps your project profile + agent files intact)
24
+ pi uninstall npm:@rootazero/pi-agent-workflow
25
+
26
+ # 2. Install the new package
27
+ pi install npm:pi-rolecast
28
+
29
+ # 3. In each project, re-run scaffolder to regenerate the profile
30
+ cd <your-project>
31
+ python3 $SKILL_ROOT/scripts/scaffolder.py init --template <lang> --force
32
+
33
+ # 4. Rename your profile file (optional — legacy name still works)
34
+ mv .pi/agent-workflow.yaml .pi/rolecast.yaml
35
+
36
+ # 5. Re-sync project-local agent files
37
+ python3 $SKILL_ROOT/scripts/sync_settings.py
38
+ ```
39
+
40
+ ## Profile diff (before / after)
41
+
42
+ **Before (v0.1.x):**
43
+
44
+ ```yaml
45
+ framework_version: 0.1.0
46
+ name: my-project
47
+ description: ...
48
+ gates:
49
+ compile: {commands: [cargo check], timeout: 300}
50
+ bindings:
51
+ architect: {alias: opus-thinking-medium, channels: [official]}
52
+ implementer: {alias: deepseek-verifiable, channels: [official]}
53
+ ```
54
+
55
+ **After (v0.2.0):**
56
+
57
+ ```yaml
58
+ framework_version: 0.2.0
59
+ name: my-project
60
+ description: ...
61
+ workflow:
62
+ role_groups: [coding]
63
+ gates:
64
+ compile: {commands: [cargo check], timeout: 300}
65
+ bindings:
66
+ coding-architect: {alias: opus-thinking-medium, channels: [official]}
67
+ coding-implementer: {alias: deepseek-verifiable, channels: [official]}
68
+ ```
69
+
70
+ ## What if I'm coming from the original `rust-agent-workflow`?
71
+
72
+ If you started on the very first `rust-agent-workflow` skill (pre-pi-agent-workflow), see the role-name translation below. The original skill used unprefixed names; pi-agent-workflow kept them; pi-rolecast prefixes them with the group.
73
+
74
+ | Original | v0.2.0 |
75
+ |---|---|
76
+ | (main) | coding-orchestrator |
77
+ | rust-architect | coding-architect |
78
+ | contract-planner | coding-planner |
79
+ | codemod | coding-implementer |
80
+ | test-writer | coding-tester |
81
+ | final-reviewer | coding-reviewer |
82
+ | repo-mapper | coding-mapper |
83
+ | perf-profiler | coding-profiler |
84
+ | safety-auditor | coding-auditor |
85
+ | relay-canary | coding-canary |
86
+ | docs-visual | coding-docs |
87
+
88
+ ## Role groups roadmap
89
+
90
+ v0.2.0 ships with the `coding` group only. Future groups planned for separate releases:
91
+
92
+ - `video` — scriptwriter, narrator-prompt, thumbnail-designer, video-editor, transcript-cleaner, caption-styler, seo-optimizer, hook-generator
93
+ - `research` — literature-reviewer, data-analyst, fact-checker, summarizer
94
+ - `design` — ux-reviewer, copywriter, asset-curator, brand-checker
95
+ - `music` — composer, lyricist, mix-engineer, mastering-engineer
96
+
97
+ To enable a group once it's installed, add it to `workflow.role_groups`. Each group ships its own aliases + bindings defaults in its templates.
98
+
99
+ ## Deprecation plan
100
+
101
+ The v0.2.0 release keeps these compatibility shims for **one** release cycle (until v0.3.0):
102
+
103
+ - `.pi/agent-workflow.yaml` still loads (with a stderr hint).
104
+ - Legacy unprefixed role names in `bindings:` print a hint pointing to the new prefixed name.
105
+ - The framework symlink path `~/.pi/agent/pi-agent-workflow` is removed on install (warning printed if found).
106
+
107
+ After v0.3.0 these shims will be removed and v0.2.x profiles will be the only supported format.
@@ -0,0 +1,66 @@
1
+ # Profile schema reference (pi-rolecast v0.2.0)
2
+
3
+ Full schema lives at `docs/superpowers/specs/2026-10-03-pi-agent-workflow-design.md` (historical) and the live validator at `scripts/profile_loader.py`.
4
+
5
+ ## Top-level fields
6
+
7
+ | Field | Type | Required | Notes |
8
+ |---|---|---|---|
9
+ | `framework_version` | string | yes | Must match the installed framework version (e.g. `0.2.0`). |
10
+ | `name` | string | yes | Human-readable profile name. |
11
+ | `description` | string | yes | One-paragraph summary. |
12
+ | `workflow` | mapping | yes (v0.2.0+) | Holds `role_groups`. |
13
+ | `workflow.role_groups` | list[string] | yes | Which role groups are enabled. Empty list = no roles enabled. |
14
+ | `gates` | mapping | yes | Phase name → `{commands, timeout}`. May be empty. |
15
+ | `bindings` | mapping | yes | Full role name (`<group>-<role>` or custom name) → `{alias, channels}`. May be empty. |
16
+ | `non_negotiables` | mapping | no | `forbidden_patterns`, `scope_constraints`, `required_gates`. |
17
+ | `escalation` | mapping | no | `max_attempts`, `on_permanent_failure`, `preserve_logs`. |
18
+ | `trigger_overrides` | mapping | no | Phrase → `{role}`. |
19
+ | `custom_roles` | list | no | User-defined roles. |
20
+
21
+ ## Roles and groups
22
+
23
+ Roles live in `role-packs/<group>/<role>.md` in the framework installation. The v0.2.0 release ships the `coding` group with 11 roles. Each role md file has YAML frontmatter:
24
+
25
+ ```yaml
26
+ ---
27
+ name: coding-architect
28
+ category: coding
29
+ description: Design system boundaries, public APIs, error strategies.
30
+ model: deepseek-flash
31
+ thinking: high
32
+ ---
33
+ ```
34
+
35
+ The `name:` field is the full role name used in profile bindings and dispatch mentions. It must match `<group>-<role>` so the `<group>-<role>` mention syntax (`@coding-architect`) works through pi-subagents.
36
+
37
+ Profile bindings reference these full names:
38
+
39
+ ```yaml
40
+ bindings:
41
+ coding-architect: {alias: opus-thinking-medium, channels: [official]}
42
+ coding-implementer: {alias: deepseek-verifiable, channels: [official]}
43
+ # ...
44
+ ```
45
+
46
+ ## Validation rules
47
+
48
+ 1. `bindings` keys must be one of the role names from enabled `workflow.role_groups`, OR a `custom_roles` entry.
49
+ 2. Each `alias` must resolve to a non-`withdrawn` model in the merged registry.
50
+ 3. Each `channels` entry must be one the resolved model supports.
51
+ 4. `gates` phases run in declared order; `--phase <undeclared>` is a config error.
52
+ 5. Trigger phrase collisions across framework defaults + profile overrides + custom role triggers → error.
53
+ 6. `forbidden_patterns[*].pattern` must compile as a regex.
54
+ 7. `workflow.role_groups` must be a list of strings; group names not present in `role-packs/` cause the loader to skip them silently (an empty group is treated as "no roles available").
55
+
56
+ ## Migration from v0.1.x
57
+
58
+ The legacy profile filename `.pi/agent-workflow.yaml` is still recognised for one release. Profile schema changes required:
59
+
60
+ | v0.1.x field | v0.2.0 replacement |
61
+ |---|---|
62
+ | `bindings: { architect: ... }` | `bindings: { coding-architect: ... }` + `workflow.role_groups: [coding]` |
63
+ | Profile file `.pi/agent-workflow.yaml` | `.pi/rolecast.yaml` |
64
+ | (no equivalent) | `workflow.role_groups: [...]` |
65
+
66
+ The profile loader prints a one-line hint when a legacy role name is detected in a binding.
@@ -0,0 +1,14 @@
1
+ # Registry resolution reference (pi-rolecast v0.2.0)
2
+
3
+ Algorithm: spec §6.4 (7 steps).
4
+
5
+ Three override layers, deep-merged in order (later wins):
6
+ 1. Built-in: `<framework>/registry/{built_in,aliases}.yaml`
7
+ 2. User-global: `~/.pi/rolecast/{registry,aliases}-overrides.yaml` (renamed from `~/.pi/agent-workflow/` in v0.2.0)
8
+ 3. Project-local: `<project>/.pi/rolecast-registry.yaml` (renamed from `agent-workflow-registry.yaml` in v0.2.0)
9
+
10
+ Status semantics:
11
+ - `stable` — resolves normally.
12
+ - `deprecated` — resolves with a warning.
13
+ - `experimental` — resolves; scaffolder init skips it from defaults.
14
+ - `withdrawn` — does NOT resolve. Profile fails to load.
@@ -0,0 +1,27 @@
1
+ # Scaffolder usage (pi-rolecast v0.2.0)
2
+
3
+ ## init
4
+
5
+ ```bash
6
+ python3 $SKILL_ROOT/scripts/scaffolder.py init [--template LANG] [--blank] [--dry-run] [--force]
7
+ ```
8
+
9
+ Auto-detects language from project files (Cargo.toml → rust, pyproject.toml → python, package.json+tsconfig.json → typescript, go.mod → go). Multi-language projects print a list; pass `--template` to pick.
10
+
11
+ Templates ship under `<framework>/templates/{rust,typescript,python,go,blank}.yaml`. The generated profile lands at `<project>/.pi/rolecast.yaml` and includes `workflow.role_groups: [coding]` by default.
12
+
13
+ ## validate
14
+
15
+ ```bash
16
+ python3 $SKILL_ROOT/scripts/scaffolder.py validate --profile <path>
17
+ ```
18
+
19
+ Default profile path: `.pi/rolecast.yaml`. Legacy `.pi/agent-workflow.yaml` is also accepted. Delegates to `profile_loader.load_profile`. Exit code 0 = valid, non-zero = error.
20
+
21
+ ## diff
22
+
23
+ ```bash
24
+ python3 $SKILL_ROOT/scripts/scaffolder.py diff --profile <path>
25
+ ```
26
+
27
+ Reads `profile.framework_version` and reports fields added/removed in newer framework schemas. No auto-merge.
@@ -0,0 +1,67 @@
1
+ # Sync settings usage (pi-rolecast v0.2.0)
2
+
3
+ The framework's profile bindings (alias -> model + channel) need to reach the actual Pi subagent dispatcher. `sync_settings.py` is that bridge.
4
+
5
+ ## What it writes
6
+
7
+ When you run sync_settings against a project with a profile, two things happen:
8
+
9
+ 1. **settings.json** — `~/.pi/agent/settings.json` -> `subagents.agentOverrides.<full-role-name>.{model,channel}` for each bound role. (Pi core does not currently read this key for dispatch; it is kept for parity with prior skills and debugging.)
10
+ 2. **Project-local agent files** — `<project>/.pi/agents/<group>-<role>.md` is written with `model:` and `thinking:` frontmatter set from your binding. The full role name matches the binding key so pi-subagents can find it via `@<full-role-name>` mention syntax or `subagent_type: "<full-role-name>"`.
11
+
12
+ ## Commands
13
+
14
+ ```bash
15
+ python3 $SKILL_ROOT/scripts/sync_settings.py \
16
+ --profile .pi/rolecast.yaml \ # source of truth (legacy .pi/agent-workflow.yaml also accepted)
17
+ --framework-root $SKILL_ROOT # where role-packs/ lives
18
+ ```
19
+
20
+ Useful flags:
21
+ - `--status` — show current sync state vs profile bindings; flags `DRIFT` if a project-local agent file's model field was manually edited away from the binding. Exits 0 regardless (informational only).
22
+ - `--dry-run` — print what would be written without touching disk.
23
+ - `--clear` — remove all `agentOverrides` from settings.json and delete every project-local agent file. User-made files and symlinks in the agents dir are preserved.
24
+ - `--no-settings` / `--no-agents` — skip settings.json / project-local agent files respectively.
25
+ - `--agents-dir <path>` — override the default `.pi/agents/` location.
26
+ - `--settings <path>` — override `~/.pi/agent/settings.json`.
27
+ - `--list-groups` — list available role groups from `role-packs/` and exit.
28
+
29
+ ## When sync runs
30
+
31
+ - Automatically by `scripts/install.sh` whenever a profile is found in the cwd.
32
+ - Manually by you whenever you edit `.pi/rolecast.yaml` and want the change to take effect.
33
+
34
+ ## pi-subagents dependency
35
+
36
+ `@tintinweb/pi-subagents` must be installed for role dispatch to actually work. `install.sh` warns when it's missing:
37
+
38
+ ```
39
+ WARNING: pi-subagents not found in ~/.pi/agent/settings.json packages[]
40
+ Role symlinks are installed but dispatch won't work without pi-subagents.
41
+ Install with: pi install npm:@tintinweb/pi-subagents
42
+ ```
43
+
44
+ ## `model:` resolution chain
45
+
46
+ When sync_settings resolves `model:` for a binding:
47
+
48
+ 1. Profile binding specifies an alias (e.g. `opus-thinking-medium`).
49
+ 2. Alias resolution uses the 3-layer registry merge (built-in -> user-global `~/.pi/rolecast/registry-overrides.yaml` -> project-local `.pi/rolecast-registry.yaml`). The alias points to a model ID (e.g. `MiniMax-M3`).
50
+ 3. That model ID is rewritten to `provider/modelId` (see below) and written into the project-local agent file's `model:` frontmatter.
51
+
52
+ ## `thinking:` resolution
53
+
54
+ The project-local agent file's `thinking:` field is preserved from the role-packs/<group>/<role>.md default. Each role's default is set by its output category:
55
+ - Judgement roles (orchestrator, architect, auditor, reviewer): `high`
56
+ - Meta roles (mapper, planner, profiler, docs): `medium`
57
+ - Verifiable roles (implementer, tester, canary): `low`
58
+
59
+ If you want to override `thinking:` per project, edit the project-local file after sync.
60
+
61
+ ## provider/modelId format
62
+
63
+ `sync_settings.py` rewrites each binding to `provider/modelId` (e.g.
64
+ `minimax-cn/MiniMax-M3`, `openai-codex/gpt-6.1-sol`) before writing it
65
+ into the agent file. `pi-subagents` `resolveDefaultModel` only parses
66
+ strings that contain a `/`; plain `MiniMax-M3` would silently fall back to
67
+ the parent session's model. See [`dispatch-model-semantics.md`](./dispatch-model-semantics.md) for the full explanation.
@@ -0,0 +1,38 @@
1
+ # Built-in alias set. Profiles reference aliases; framework resolves them.
2
+ # Adding an alias = PR; renaming an alias = breaking change.
3
+
4
+ aliases:
5
+ opus-thinking-medium:
6
+ preferred: claude-opus-5-5
7
+ fallback_chain: [claude-sonnet-5-5]
8
+ notes: "Frontier reasoning + thinking; judgement work"
9
+
10
+ opus-thinking-high:
11
+ preferred: claude-opus-5-5
12
+ fallback_chain: []
13
+ notes: "High-effort reasoning"
14
+
15
+ gpt-judgment-medium:
16
+ preferred: gpt-6.1-sol
17
+ fallback_chain: []
18
+ notes: "Judgement + relay channel; output reviewed"
19
+
20
+ gpt-judgment-high:
21
+ preferred: gpt-6.1-sol
22
+ fallback_chain: []
23
+ notes: "High-effort judgement"
24
+
25
+ deepseek-verifiable:
26
+ preferred: deepseek-v4.1-flash
27
+ fallback_chain: []
28
+ notes: "Verifiable-output work; trusted channel only"
29
+
30
+ minimax-medium:
31
+ preferred: minimax-m3
32
+ fallback_chain: []
33
+ notes: "Generation + general purpose"
34
+
35
+ minimax-fast:
36
+ preferred: minimax-m3
37
+ fallback_chain: []
38
+ notes: "Cheap, fast"
@@ -0,0 +1,42 @@
1
+ # Built-in model registry shipped with pi-agent-workflow.
2
+ # Updated via framework version bumps. Add new models here; never mutate a
3
+ # shipped model — change `status: deprecated` or `withdrawn` instead.
4
+
5
+ models:
6
+ - id: claude-opus-5-5
7
+ vendor: anthropic
8
+ capabilities: {reasoning: high, thinking: true, context_window: 200000}
9
+ channels:
10
+ - {id: official, trust: trusted}
11
+ - {id: relay-default, trust: unverified}
12
+ cost_tier: high
13
+ status: stable
14
+
15
+ - id: claude-sonnet-5-5
16
+ vendor: anthropic
17
+ capabilities: {reasoning: medium, thinking: false, context_window: 200000}
18
+ channels:
19
+ - {id: official, trust: trusted}
20
+ cost_tier: medium
21
+ status: stable
22
+
23
+ - id: deepseek-v4.1-flash
24
+ vendor: deepseek
25
+ capabilities: {reasoning: medium, thinking: false, context_window: 64000}
26
+ channels: [{id: official, trust: trusted}]
27
+ cost_tier: low
28
+ status: stable
29
+
30
+ - id: gpt-6.1-sol
31
+ vendor: openai
32
+ capabilities: {reasoning: high, thinking: true, context_window: 128000}
33
+ channels: [{id: relay-default, trust: unverified}]
34
+ cost_tier: medium
35
+ status: stable
36
+
37
+ - id: minimax-m3
38
+ vendor: minimax
39
+ capabilities: {reasoning: medium, thinking: false, context_window: 200000}
40
+ channels: [{id: official, trust: trusted}]
41
+ cost_tier: low
42
+ status: stable
@@ -0,0 +1,2 @@
1
+ PyYAML>=6.0,<7
2
+ pytest>=7.0,<10