@firatcand/roster 0.4.0 → 1.0.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 (76) hide show
  1. package/README.md +77 -220
  2. package/agents/lesson-drafter.md +3 -8
  3. package/agents/pattern-detector.md +0 -1
  4. package/bin/roster.js +168 -57
  5. package/package.json +2 -3
  6. package/skills/chief-of-staff/SKILL.md +62 -78
  7. package/skills/dreamer/SKILL.md +8 -7
  8. package/skills/roster-orchestrator/SKILL.md +53 -25
  9. package/templates/CLAUDE.project.template.md +1 -1
  10. package/templates/CONTEXT.template.md +2 -2
  11. package/templates/gitignore-defaults.txt +2 -0
  12. package/templates/scaffold/chief-of-staff/README.md +16 -24
  13. package/templates/scaffold/chief-of-staff/agent.md +22 -32
  14. package/templates/scaffold/chief-of-staff/plans/audit-agent.yaml +4 -4
  15. package/templates/scaffold/chief-of-staff/plans/audit-repo.yaml +5 -4
  16. package/templates/scaffold/chief-of-staff/plans/create-agent.yaml +5 -34
  17. package/templates/scaffold/config/project.yaml.template +10 -0
  18. package/templates/scaffold/conventions.md +159 -171
  19. package/templates/scaffold/dreamer/README.md +2 -2
  20. package/templates/scaffold/dreamer/agent.md +0 -1
  21. package/templates/scaffold/dreamer/plans/nightly-reflection.yaml +23 -37
  22. package/templates/scaffold/dreamer/subagents/lesson-drafter.md +2 -7
  23. package/templates/scaffold/{projects/_demo/guidelines → guidelines}/asset-links.md +4 -0
  24. package/templates/scaffold/{projects/_demo/guidelines → guidelines}/brand-book.md +4 -0
  25. package/templates/scaffold/{projects/_demo/guidelines → guidelines}/messaging.md +4 -0
  26. package/templates/scaffold/{projects/_demo/guidelines → guidelines}/voice.md +4 -0
  27. package/templates/scaffold/scripts/audit-agent.sh +74 -47
  28. package/templates/scaffold/scripts/audit-repo.sh +27 -49
  29. package/templates/scaffold/scripts/create-function.sh +1 -1
  30. package/templates/scaffold/scripts/lib/README.md +1 -1
  31. package/templates/scaffold/scripts/lib/bindings-prompt.sh +41 -124
  32. package/templates/scaffold/scripts/new-agent.sh +97 -91
  33. package/templates/scaffold/scripts/rename-agent.sh +91 -0
  34. package/templates/scaffold/scripts/save-state.sh +32 -0
  35. package/agents/critic.md +0 -74
  36. package/agents/enricher.md +0 -56
  37. package/agents/promotion-arbiter.md +0 -71
  38. package/agents/prospector.md +0 -51
  39. package/agents/writer.md +0 -58
  40. package/skills/sdr/SKILL.md +0 -147
  41. package/templates/scaffold/chief-of-staff/plans/add-agent-to-project.yaml +0 -45
  42. package/templates/scaffold/chief-of-staff/plans/archive-project.yaml +0 -51
  43. package/templates/scaffold/chief-of-staff/plans/audit-project.yaml +0 -34
  44. package/templates/scaffold/chief-of-staff/plans/create-project.yaml +0 -65
  45. package/templates/scaffold/chief-of-staff/plans/remove-agent-from-project.yaml +0 -50
  46. package/templates/scaffold/chief-of-staff/plans/rename-project.yaml +0 -62
  47. package/templates/scaffold/chief-of-staff/plans/unarchive-project.yaml +0 -41
  48. package/templates/scaffold/dreamer/subagents/promotion-arbiter.md +0 -64
  49. package/templates/scaffold/gtm/sdr/.claude/settings.json +0 -3
  50. package/templates/scaffold/gtm/sdr/.mcp.json +0 -21
  51. package/templates/scaffold/gtm/sdr/README.md +0 -41
  52. package/templates/scaffold/gtm/sdr/agent.md +0 -136
  53. package/templates/scaffold/gtm/sdr/plans/cold-outreach.yaml +0 -92
  54. package/templates/scaffold/gtm/sdr/projects/_demo/asset-references.md +0 -7
  55. package/templates/scaffold/gtm/sdr/projects/_demo/config/default.yaml +0 -69
  56. package/templates/scaffold/gtm/sdr/projects/_demo/log/feedback/.gitkeep +0 -0
  57. package/templates/scaffold/gtm/sdr/projects/_demo/log/runs/.gitkeep +0 -0
  58. package/templates/scaffold/gtm/sdr/projects/_demo/playbook/.gitkeep +0 -0
  59. package/templates/scaffold/gtm/sdr/subagents/critic.md +0 -67
  60. package/templates/scaffold/gtm/sdr/subagents/enricher.md +0 -49
  61. package/templates/scaffold/gtm/sdr/subagents/prospector.md +0 -44
  62. package/templates/scaffold/gtm/sdr/subagents/writer.md +0 -51
  63. package/templates/scaffold/projects/_demo/CLAUDE.md +0 -35
  64. package/templates/scaffold/projects/_demo/README.md +0 -16
  65. package/templates/scaffold/projects/_demo/assets/.gitkeep +0 -0
  66. package/templates/scaffold/projects/_demo/config/default.yaml +0 -28
  67. package/templates/scaffold/projects/_demo/state.md +0 -11
  68. package/templates/scaffold/scripts/archive-project.sh +0 -98
  69. package/templates/scaffold/scripts/audit-project.sh +0 -361
  70. package/templates/scaffold/scripts/new-agent-instance.sh +0 -114
  71. package/templates/scaffold/scripts/new-project.sh +0 -125
  72. package/templates/scaffold/scripts/remove-agent-from-project.sh +0 -67
  73. package/templates/scaffold/scripts/rename-project.sh +0 -118
  74. package/templates/scaffold/scripts/unarchive-project.sh +0 -115
  75. /package/templates/scaffold/gtm/{sdr/playbook/.gitkeep → .gitkeep} +0 -0
  76. /package/templates/scaffold/{projects/_demo/guidelines → guidelines}/icps/_persona-template.md +0 -0
@@ -1,136 +1,53 @@
1
1
  #!/usr/bin/env bash
2
- # bindings-prompt.sh — read ## Tools and bindings from agent.md, prompt user, append YAML
2
+ # bindings-prompt.sh — DISABLED in v1.0 (ROS-78).
3
3
  #
4
- # Args:
5
- # $1 = path to agent.md (the global agent contract)
6
- # $2 = path to instance config/default.yaml (will append tools: block)
4
+ # Pre-v1.0 behavior: read `## Tools and bindings` from agent.md (legacy
5
+ # two-level `tool: key: {required, description}` schema), prompt the user
6
+ # for binding values, and append a `tools:` block to a project-instance
7
+ # config at `projects/<inst>/config/default.yaml`.
7
8
  #
8
- # Behavior:
9
- # 1. Extract YAML block from `## Tools and bindings` in agent.md
10
- # 2. For each tool/key, prompt user via /dev/tty for value (showing required/optional + description)
11
- # 3. Empty input or "skip" write `# TODO: <description>` placeholder
12
- # 4. Append a `tools:` block to the instance config
9
+ # Both inputs change in v1.0:
10
+ # 1. The shipped `## Tools and bindings` block in agent.md is now a flat
11
+ # schema (`tool: { env_var, required, description }` per
12
+ # conventions.md). The legacy parser silently emits an empty
13
+ # `tools.<tool>:` block when it encounters scalar values where it
14
+ # expects a mapping.
15
+ # 2. The instance-config target is gone — agent config lives at
16
+ # `<function>/<agent>/config.yaml`, and env-var values belong in
17
+ # workspace `/.env` (overridable in `<agent>/.env`).
13
18
  #
14
- # Non-TTY environments fall back to TODO placeholders for every binding.
19
+ # The proper v1.0 flow (read agent.md flat schema write metadata to
20
+ # config.yaml `tools:` block → prompt for required env-var values and
21
+ # append to `/.env`) requires the env-merge loader that ships in Phase 2.
22
+ # Rather than ship a script whose advertised behavior is broken against
23
+ # the new schema, this script aborts with manual-configuration instructions
24
+ # (edit agent.md schema → mirror to config.yaml → fill /.env).
25
+ #
26
+ # Tracking: re-enable as part of the Phase 2 cli-plumbing reshape
27
+ # (env-merge loader + doctor checks 13-15).
15
28
 
16
29
  set -euo pipefail
17
30
 
18
- AGENT_MD="${1:-}"
19
- INSTANCE_CONFIG="${2:-}"
20
-
21
- if [ -z "$AGENT_MD" ] || [ -z "$INSTANCE_CONFIG" ]; then
22
- echo "Usage: $0 <agent.md> <instance-config/default.yaml>" >&2
23
- exit 1
24
- fi
25
-
26
- if [ ! -f "$AGENT_MD" ]; then
27
- echo "ERROR: agent.md not found at $AGENT_MD" >&2
28
- exit 1
29
- fi
30
- if [ ! -f "$INSTANCE_CONFIG" ]; then
31
- echo "ERROR: instance config not found at $INSTANCE_CONFIG" >&2
32
- exit 1
33
- fi
34
-
35
- if ! command -v python3 >/dev/null 2>&1; then
36
- echo "ERROR: python3 is required for bindings-prompt.sh" >&2
37
- exit 1
38
- fi
39
-
40
- # Drive prompts + YAML emission via python; pass file paths via env to avoid quoting hell.
41
- export AGENT_MD INSTANCE_CONFIG
42
-
43
- FINAL_YAML=$(python3 << 'PYEOF'
44
- import os, re, sys
45
-
46
- agent_md = os.environ["AGENT_MD"]
47
- with open(agent_md) as f:
48
- content = f.read()
49
-
50
- m = re.search(r'## Tools and bindings.*?\n```yaml\n(.*?)\n```', content, re.DOTALL)
51
- if not m:
52
- sys.stderr.write(f"ERROR: no '## Tools and bindings' YAML block in {agent_md}\n")
53
- sys.exit(1)
54
-
55
- schema_text = m.group(1)
56
-
57
- try:
58
- import yaml
59
- except ImportError:
60
- sys.stderr.write("ERROR: pyyaml required (pip3 install --user pyyaml)\n")
61
- sys.exit(1)
62
-
63
- try:
64
- schema = yaml.safe_load(schema_text)
65
- except Exception as e:
66
- sys.stderr.write(f"ERROR parsing bindings schema: {e}\n")
67
- sys.exit(1)
68
-
69
- if not isinstance(schema, dict):
70
- sys.stderr.write("Bindings schema is not a YAML mapping\n")
71
- sys.exit(1)
72
-
73
- # Try to open /dev/tty for interactive input. Fall back to all-TODO if unavailable.
74
- try:
75
- tty = open("/dev/tty", "r")
76
- interactive = True
77
- except OSError:
78
- tty = None
79
- interactive = False
80
- sys.stderr.write("(non-interactive environment — all bindings will be TODO placeholders)\n")
81
-
82
- def yaml_quote(value: str) -> str:
83
- if value == "":
84
- return '""'
85
- if any(c in value for c in [":", "#", "@", "{", "}", "[", "]", ",", "&", "*", "!", "|", ">", "'", '"', "%", "`"]):
86
- escaped = value.replace('\\', '\\\\').replace('"', '\\"')
87
- return f'"{escaped}"'
88
- return value
89
-
90
- out_lines = []
91
- out_lines.append("")
92
- out_lines.append("# Tool bindings (filled via chief-of-staff scaffolding prompt)")
93
- out_lines.append("tools:")
94
-
95
- for tool, bindings in schema.items():
96
- if not isinstance(bindings, dict):
97
- continue
98
- out_lines.append(f" {tool}:")
99
- for key, meta in bindings.items():
100
- if not isinstance(meta, dict):
101
- continue
102
- required = bool(meta.get("required", False))
103
- description = str(meta.get("description", "") or "")
104
- marker = "(required)" if required else "(optional)"
105
-
106
- value = ""
107
- if interactive:
108
- sys.stderr.write(f"\n {tool}.{key} {marker}\n")
109
- sys.stderr.write(f" {description}\n")
110
- sys.stderr.write(f" > ")
111
- sys.stderr.flush()
112
- try:
113
- value = tty.readline().strip()
114
- except (OSError, KeyboardInterrupt):
115
- value = ""
31
+ cat >&2 <<'MSG'
32
+ bindings-prompt.sh is disabled in Roster v1.0.
116
33
 
117
- if value == "" or value.lower() == "skip":
118
- out_lines.append(f" {key}: # TODO: {description}")
119
- else:
120
- out_lines.append(f" {key}: {yaml_quote(value)}")
34
+ The legacy two-level schema parser this script uses is incompatible with
35
+ the flat ## Tools and bindings schema documented in conventions.md
36
+ ("Tool bindings" section). The Phase 2 reshape (env-merge loader +
37
+ config.yaml/.env split) will rebuild this flow.
121
38
 
122
- print("\n".join(out_lines))
39
+ Until Phase 2 lands, configure tool bindings by hand:
123
40
 
124
- if tty is not None:
125
- tty.close()
126
- PYEOF
127
- )
41
+ 1. Open <function>/<agent>/agent.md and confirm the ## Tools and
42
+ bindings YAML block lists each tool with env_var, required, and
43
+ description fields (see conventions.md § "Tool bindings").
44
+ 2. Mirror that block as the tools: mapping in
45
+ <function>/<agent>/config.yaml.
46
+ 3. Add the corresponding env var values to workspace /.env (or, for
47
+ agent-scoped overrides, <function>/<agent>/.env).
128
48
 
129
- # Append to instance config
130
- {
131
- echo ""
132
- echo "$FINAL_YAML"
133
- } >> "$INSTANCE_CONFIG"
49
+ (The chief-of-staff guided create-agent flow shipped in v0.4 is also on
50
+ the pre-v1 shape; it will be updated alongside the env-merge loader.)
51
+ MSG
134
52
 
135
- echo "" >&2
136
- echo "✓ Tool bindings appended to $INSTANCE_CONFIG" >&2
53
+ exit 2
@@ -62,7 +62,7 @@ description: "$fn agent — TODO: fill in description"
62
62
 
63
63
  # /$name
64
64
 
65
- You are operating the \`$fn/$name\` agent. Load \`$fn/$name/agent.md\` and the project's relevant context.
65
+ You are operating the \`$fn/$name\` agent. Load \`$fn/$name/agent.md\` and the workspace's relevant context.
66
66
 
67
67
  The user request is: \$ARGUMENTS
68
68
 
@@ -70,28 +70,25 @@ The user request is: \$ARGUMENTS
70
70
 
71
71
  Parse the user request:
72
72
 
73
- 1. **If it matches \`run <plan-name> for <project>\` or \`run <plan-name> on <project>\`**:
73
+ 1. **If it matches \`run <plan-name>\`**:
74
74
  - Load \`$fn/$name/plans/<plan-name>.yaml\`. If it doesn't exist, list available plans and ask user to pick.
75
- - Load \`projects/<project>/CLAUDE.md\` and relevant guidelines.
76
- - Load \`$fn/$name/projects/<project>/config/default.yaml\`.
77
- - Validate that all required tool bindings are non-TODO. Abort if not.
78
- - Execute the plan steps. Substitute \`\${tools.X.Y}\`, \`\${inputs.X}\`, \`\${config.X}\`.
79
- - Log to \`$fn/$name/projects/<project>/log/runs/<YYYY-MM>/<YYYY-MM-DD-HHMM>.md\`.
80
- - Surface HITL approvals per the plan's approval_channel.
81
-
82
- 2. **If only a project is named (no plan)**:
75
+ - Load \`$fn/$name/config.yaml\` and resolve env via \`resolveAgentEnv\` (\`$fn/$name/.env\` overrides workspace \`/.env\`).
76
+ - Load workspace guidelines referenced under \`config.yaml\` \`guideline_refs:\` (e.g., \`/guidelines/voice.md\`, \`/guidelines/icps/\`, \`/guidelines/messaging.md\`).
77
+ - Validate that all required tool bindings have non-empty env vars. Abort with a clear message if not.
78
+ - Execute the plan steps. Substitute \`\${tools.X.env_var}\`, \`\${inputs.X}\`, \`\${config.X}\`.
79
+ - Log to \`$fn/$name/logs/runs/<YYYY-MM>/<YYYY-MM-DD-HHMM>.md\`.
80
+ - Surface HITL approvals per the plan's \`approval_channel\`.
81
+
82
+ 2. **If no plan is named**:
83
83
  - List available plans from \`$fn/$name/plans/\` with descriptions. Ask user to pick.
84
84
 
85
- 3. **If neither plan nor project is named**:
86
- - List available projects and plans. Ask user to specify both.
87
-
88
- 4. **For ad-hoc strategic work**: suggest invoking \`$fn/EXPERT.md\` instead.
85
+ 3. **For ad-hoc strategic work**: suggest invoking \`$fn/EXPERT.md\` instead.
89
86
 
90
87
  ## Constraints
91
88
 
92
89
  - Only run plans that exist as files in \`$fn/$name/plans/\`.
93
90
  - Don't bypass approval gates.
94
- - File writes go to the instance's \`log/runs/\` unless the plan explicitly writes elsewhere.
91
+ - File writes go to \`$fn/$name/logs/runs/\` unless the plan explicitly writes elsewhere.
95
92
  EOF
96
93
  }
97
94
 
@@ -137,7 +134,7 @@ fi
137
134
 
138
135
  echo "Creating agent: $FN/$NAME"
139
136
 
140
- mkdir -p "$TARGET"/{subagents,playbook,logs,projects/_template,.claude/skills,.claude/plugins}
137
+ mkdir -p "$TARGET"/{subagents,playbook,pending,logs/runs,logs/feedback,.claude/skills,.claude/plugins}
141
138
 
142
139
  # agent.md stub
143
140
  cat > "$TARGET/agent.md" << EOF
@@ -149,45 +146,36 @@ cat > "$TARGET/agent.md" << EOF
149
146
 
150
147
  ## Inputs
151
148
 
152
- The orchestrator expects:
153
-
154
- - \`project\`: project slug
155
- - <other inputs>
149
+ The orchestrator expects per-plan inputs (declared in each plan's \`inputs:\` block).
156
150
 
157
151
  Read at runtime:
158
152
 
159
153
  - \`agent.md\` (this file)
160
- - \`projects/<project>/<this-agent>/config/default.yaml\`
161
- - \`projects/<project>/CLAUDE.md\`
162
- - \`projects/<project>/guidelines/voice.md\`
163
- - <other guidelines this agent uses>
164
- - \`<this-agent>/projects/<project>/playbook/\` — project-scoped lessons
165
- - \`<this-agent>/playbook/\` — global lessons
154
+ - \`config.yaml\` (workspace-root-relative guideline refs + tool bindings)
155
+ - Workspace guidelines referenced under \`config.yaml\` \`guideline_refs:\` (e.g., \`/guidelines/voice.md\`, \`/guidelines/icps/\`, \`/guidelines/messaging.md\`)
156
+ - \`playbook/\` — validated lessons (single playbook per agent)
166
157
 
167
- ## Steps
158
+ Env resolution: \`<this-agent>/.env\` overrides workspace \`/.env\`. Required tool env vars validated before the plan runs.
168
159
 
169
- 1. Resolve config and context
170
- 2. <step>
171
- 3. <step>
160
+ ## Plans
172
161
 
173
- ## Subagents
162
+ Named plans this agent runs (files in \`plans/<plan>.yaml\`). One-line description per plan.
163
+ No default plan — invoking without a plan triggers an interactive "which plan?" prompt.
174
164
 
175
- - <subagent-name>.md <one-liner>
165
+ - <plan-name>: <one-liner>
176
166
 
177
- ## Tools
178
-
179
- Agent-scoped MCPs at \`<this-agent>/.mcp.json\`:
180
- - <tool/MCP> — <purpose>
167
+ ## Subagents
181
168
 
182
- Universal MCPs (Slack, Google Drive) inherited from agent-team root.
169
+ - <subagent-name>.md <one-liner>
183
170
 
184
171
  ## Outputs
185
172
 
186
- Run file at \`projects/<project>/<this-agent>/log/runs/<YYYY-MM>/<YYYY-MM-DD-HHMM>.md\`. See \`conventions.md\` § "Run file format".
173
+ Run file at \`logs/runs/<YYYY-MM>/<YYYY-MM-DD-HHMM>.md\`. See \`conventions.md\` § "Run file format".
174
+ Per-plan output schemas live in each plan's \`outputs:\` block.
187
175
 
188
176
  ## Approval
189
177
 
190
- \`approval_channel: auto\` — in-session if interactive, Slack \`#${FN}\` if cron (resolved via \`SLACK_HITL_CHANNEL_$(echo "$FN" | tr '[:lower:]-' '[:upper:]_')\` in \`.env\`).
178
+ \`approval_channel: auto\` — in-session if interactive, Slack \`#${FN}\` if cron (resolved via \`SLACK_HITL_CHANNEL_$(echo "$FN" | tr '[:lower:]-' '[:upper:]_')\` in workspace \`/.env\`).
191
179
 
192
180
  ## Lessons protocol
193
181
 
@@ -206,39 +194,49 @@ cat > "$TARGET/README.md" << EOF
206
194
 
207
195
  ## Files
208
196
 
209
- - \`agent.md\` — orchestrator contract
197
+ - \`agent.md\` — orchestrator contract (behavioral prompt, plans list, tool bindings schema)
198
+ - \`config.yaml\` — guideline refs + tool bindings (workspace-root paths)
199
+ - \`.env\` — agent-scoped env overrides (gitignored, 0600 — optional, inherits from workspace \`/.env\`)
200
+ - \`plans/\` — named workflows (\`<plan>.yaml\`)
210
201
  - \`subagents/\` — specialized roles
211
- - \`playbook/\` — global lessons (one file per lesson)
212
- - \`logs/\` — agent-level operational logs
213
- - \`.claude/\` — agent-scoped skills, plugins
214
- - \`.mcp.json\` — agent-scoped MCPs (CREATE THIS see template comment)
215
- - \`projects/\` — per-project instances
202
+ - \`playbook/\` — validated lessons (single playbook per agent)
203
+ - \`pending/\` — HITL items awaiting approval
204
+ - \`logs/runs/\`, \`logs/feedback/\` — run outputs + mirrored feedback
205
+ - \`asset-references.md\` — which workspace assets this agent uses (thin pointer)
206
+ - \`.claude/\` — agent-scoped Claude Code config (skills, plugins, settings)
207
+ - \`.mcp.json\` — agent-scoped MCPs
216
208
 
217
209
  ## Invocation
218
210
 
219
- From a project instance session:
211
+ From the workspace root:
220
212
 
221
213
  \`\`\`bash
222
- cd $FN/$NAME/projects/<project>/
223
214
  claude
224
- "Run $NAME on <inputs>"
215
+ > /$NAME run <plan-name>
225
216
  \`\`\`
226
217
 
227
- From cron: see ROS-39 (Phase 2.5 scheduling primitives — wrapper layout + install script land then).
218
+ Or via natural language:
219
+
220
+ \`\`\`
221
+ "Run $FN/$NAME using the <plan-name> plan"
222
+ \`\`\`
223
+
224
+ From cron: see ADR-0001 (subscription-billed scheduling via native local schedulers). Install via \`roster schedule install $FN/$NAME <plan> --cron "<expr>" --tool claude|codex\`.
228
225
 
229
226
  ## Configuration
230
227
 
231
- Per-project: \`projects/<proj>/$FN/$NAME/config/default.yaml\` (created by \`new-agent-instance.sh\`).
228
+ \`config.yaml\` (this agent) — guideline refs + tool bindings.
229
+ Workspace \`/.env\` (root) + optional \`<this-agent>/.env\` for agent-scoped overrides.
232
230
 
233
231
  ## Outputs
234
232
 
235
- \`projects/<proj>/$FN/$NAME/log/runs/<YYYY-MM>/<YYYY-MM-DD-HHMM>.md\`
233
+ \`logs/runs/<YYYY-MM>/<YYYY-MM-DD-HHMM>.md\` — one file per invocation.
236
234
  EOF
237
235
 
238
236
  # .mcp.json stub
239
237
  cat > "$TARGET/.mcp.json" << EOF
240
238
  {
241
- "_comment": "Agent-scoped MCPs for $NAME. Available when working in this agent's tree (including project instances). Add MCPs this agent specifically needs. Universal MCPs (Slack, Google Drive) are inherited from agent-team/.mcp.json.",
239
+ "_comment": "Agent-scoped MCPs for $NAME. Available when working in this agent's tree. Add MCPs this agent specifically needs. Universal MCPs (Slack, Google Drive) are inherited from the workspace .mcp.json.",
242
240
  "mcpServers": {}
243
241
  }
244
242
  EOF
@@ -273,41 +271,48 @@ cat > "$TARGET/subagents/_template.md" << 'EOF'
273
271
  <Specific criteria for acceptable output.>
274
272
  EOF
275
273
 
276
- # Project instance template
277
- mkdir -p "$TARGET/projects/_template/config"
278
- mkdir -p "$TARGET/projects/_template/playbook"
279
- mkdir -p "$TARGET/projects/_template/log/runs"
280
- mkdir -p "$TARGET/projects/_template/log/feedback"
281
-
282
- cat > "$TARGET/projects/_template/config/default.yaml" << EOF
283
- ---
284
- agent: $NAME
285
- project: <project-slug>
286
- created: <YYYY-MM-DD>
287
- last_modified: <YYYY-MM-DD>
288
- ---
289
-
290
- # $NAME Config — <Project>
291
-
292
- # See $FN/$NAME/agent.md § "Inputs" for required fields.
293
- # Use prose comments to explain "why" alongside "what".
274
+ # config.yaml agent config (guideline refs + tool bindings)
275
+ # Minimal stub. Until the Phase 2 env-merge loader lands, bindings are
276
+ # hand-edited: copy the ## Tools and bindings YAML block from agent.md
277
+ # into the tools: mapping below, then fill the corresponding env vars
278
+ # in workspace /.env (or this agent's .env).
279
+ cat > "$TARGET/config.yaml" << EOF
280
+ agent: $FN/$NAME
281
+ plans_dir: ./plans/
282
+
283
+ # Workspace-root-relative refs. Loader rejects literal absolute fs paths
284
+ # like /Users/, /home/, /etc/, /var/, /tmp/, /opt/.
285
+ guideline_refs:
286
+ voice: /guidelines/voice.md
287
+ icps: /guidelines/icps/
288
+ messaging: /guidelines/messaging.md
289
+ # add more as needed:
290
+ # brand_book: /guidelines/brand-book.md
291
+ # do_and_dont: /guidelines/do-and-dont.md
292
+ # compliance: /guidelines/compliance.md
293
+ # competitors: /guidelines/competitors.md
294
+
295
+ # Tool bindings. Each tool entry names the env var, required flag, and a
296
+ # short description. Env vars themselves live in workspace /.env (or are
297
+ # overridden in this agent's .env).
298
+ tools: {}
294
299
  EOF
295
300
 
296
- cat > "$TARGET/projects/_template/asset-references.md" << EOF
297
- # Asset references $NAME / <project>
301
+ # asset-references.md thin pointer at agent root
302
+ cat > "$TARGET/asset-references.md" << EOF
303
+ # Asset references — $FN/$NAME
298
304
 
299
- This agent uses these assets from \`projects/<project>/guidelines/asset-links.md\`:
305
+ This agent uses these assets from \`guidelines/asset-links.md\`:
300
306
 
301
307
  - <e.g., specific asset by name>
302
308
  EOF
303
309
 
304
310
  touch "$TARGET/playbook/.gitkeep"
305
- touch "$TARGET/logs/.gitkeep"
311
+ touch "$TARGET/pending/.gitkeep"
312
+ touch "$TARGET/logs/runs/.gitkeep"
313
+ touch "$TARGET/logs/feedback/.gitkeep"
306
314
  touch "$TARGET/.claude/skills/.gitkeep"
307
315
  touch "$TARGET/.claude/plugins/.gitkeep"
308
- touch "$TARGET/projects/_template/playbook/.gitkeep"
309
- touch "$TARGET/projects/_template/log/runs/.gitkeep"
310
- touch "$TARGET/projects/_template/log/feedback/.gitkeep"
311
316
 
312
317
  # === Tool bindings prompt (added by tool-bindings workflow) ===
313
318
  # Ask the user whether to define tools now. If yes, collect tool names and scaffold
@@ -346,24 +351,25 @@ if [ -t 0 ] && [ "${AGENT_TEAM_NO_CONFIRM:-0}" != "1" ]; then
346
351
  echo ""
347
352
  echo "## Tools and bindings"
348
353
  echo ""
349
- echo "Per-project tool bindings expected by this agent. Chief-of-staff prompts for these when scaffolding a new agent-instance. Values land in \`projects/<project>/config/default.yaml\` under a \`tools:\` key."
354
+ echo "Tool bindings expected by this agent. Until the Phase 2 env-merge loader ships, configure them by hand: mirror the YAML block below into \`<agent>/config.yaml\` under a \`tools:\` key, and put the env var values in workspace \`/.env\` (or \`<agent>/.env\` for agent-scoped overrides)."
350
355
  echo ""
351
- echo "Fill in each tool's bindings below. Schema: each binding has a \`required\` flag (true/false) and a \`description\`."
356
+ echo "Fill in each tool's bindings below. Schema per conventions.md § \"Tool bindings\": each tool has a \`env_var\` (the env-var name the runtime reads), a \`required\` flag (true/false), and a one-line \`description\`."
352
357
  echo ""
353
358
  echo '```yaml'
354
359
  for tool in "${TOOL_NAMES[@]}"; do
360
+ tool_env=$(echo "$tool" | tr '[:lower:]-' '[:upper:]_')
355
361
  echo "$tool:"
356
- echo " # TODO: define bindings"
357
- echo " # <binding_name>:"
358
- echo " # required: true"
359
- echo " # description: \"...\""
362
+ echo " env_var: ${tool_env}_API_KEY # TODO: confirm env var name"
363
+ echo " required: true # TODO: confirm required vs optional"
364
+ echo " description: \"\" # TODO: one-line description"
360
365
  done
361
366
  echo '```'
362
367
  } >> "$NEW_AGENT_MD"
363
368
 
364
369
  echo ""
365
370
  echo "✓ Added '## Tools and bindings' to $NEW_AGENT_MD with stubs for: ${TOOL_NAMES[*]}"
366
- echo " Edit agent.md to fill in actual bindings before adding instances."
371
+ echo " Edit agent.md to fill in env_var names + descriptions, then mirror the tools: block into <agent>/config.yaml by hand."
372
+ echo " (Phase 2 will add an env-merge loader + automated config.yaml/.env wiring; until then this step is manual.)"
367
373
  else
368
374
  echo " No valid tool names provided. Skipping section."
369
375
  fi
@@ -399,12 +405,12 @@ echo ""
399
405
  echo "✓ Agent '$FN/$NAME' created at $TARGET"
400
406
  echo ""
401
407
  echo "Next steps:"
402
- echo " 1. Fill in $TARGET/agent.md (purpose, inputs, steps, subagents, tools, outputs)"
403
- echo " 2. Add subagents: cp $TARGET/subagents/_template.md $TARGET/subagents/<name>.md and fill in"
404
- echo " 3. Add agent-scoped MCPs to $TARGET/.mcp.json if needed (HeyReach, Apollo, etc.)"
405
- echo " 4. Update $TARGET/README.md with a real description"
406
- echo " 5. Add at least one plan to $TARGET/plans/ (e.g., $TARGET/plans/<plan-name>.yaml)"
407
- echo " 6. Edit .claude/commands/$NAME.md to fill in the description"
408
- echo " 7. Add an instance to a project: bash scripts/new-agent-instance.sh <project> $FN $NAME"
408
+ echo " 1. Fill in $TARGET/agent.md (purpose, inputs, plans, subagents, tools, outputs)"
409
+ echo " 2. Fill in $TARGET/config.yaml (guideline_refs, tools)"
410
+ echo " 3. Add subagents: cp $TARGET/subagents/_template.md $TARGET/subagents/<name>.md and fill in"
411
+ echo " 4. Add agent-scoped MCPs to $TARGET/.mcp.json if needed (HeyReach, Apollo, etc.)"
412
+ echo " 5. Update $TARGET/README.md with a real description"
413
+ echo " 6. Add at least one plan to $TARGET/plans/ (e.g., $TARGET/plans/<plan-name>.yaml)"
414
+ echo " 7. Edit .claude/commands/$NAME.md to fill in the description"
409
415
  echo ""
410
416
  echo "Reference: see gtm/sdr/ for a complete example."
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env bash
2
+ # rename-agent.sh — renames a global agent everywhere it appears
3
+ # Usage: bash scripts/rename-agent.sh <function> <old> <new>
4
+
5
+ set -euo pipefail
6
+
7
+ if [ $# -ne 3 ]; then
8
+ echo "Usage: $0 <function> <old> <new>"
9
+ exit 1
10
+ fi
11
+
12
+ FN="$1"
13
+ OLD="$2"
14
+ NEW="$3"
15
+ ROOT="$(cd "$(dirname "$0")/.." && pwd)"
16
+
17
+ if ! [[ "$NEW" =~ ^[a-z][a-z0-9-]*$ ]]; then
18
+ echo "ERROR: New slug must be lowercase, alphanumeric + hyphens, starting with a letter."
19
+ exit 1
20
+ fi
21
+
22
+ OLD_DIR="$ROOT/$FN/$OLD"
23
+ NEW_DIR="$ROOT/$FN/$NEW"
24
+
25
+ if [ ! -d "$OLD_DIR" ]; then
26
+ echo "ERROR: Agent '$FN/$OLD' not found at $OLD_DIR"
27
+ exit 1
28
+ fi
29
+
30
+ if [ -d "$NEW_DIR" ]; then
31
+ echo "ERROR: Agent '$FN/$NEW' already exists at $NEW_DIR"
32
+ exit 1
33
+ fi
34
+
35
+ TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
36
+
37
+ mv "$OLD_DIR" "$NEW_DIR"
38
+ echo " Moved: $FN/$OLD/ → $FN/$NEW/"
39
+
40
+ SED_INPLACE=(-i)
41
+ if [[ "$(uname)" == "Darwin" ]]; then
42
+ SED_INPLACE=(-i '')
43
+ fi
44
+
45
+ # Broad replace on prose files only — these are markdown stubs where the
46
+ # old slug appears in headings / paths and we want every reference updated.
47
+ for f in "$NEW_DIR"/agent.md "$NEW_DIR"/README.md "$NEW_DIR"/asset-references.md; do
48
+ [ -f "$f" ] && sed "${SED_INPLACE[@]}" "s|$OLD|$NEW|g" "$f"
49
+ done
50
+
51
+ # config.yaml: only the identity field. A broad replace would corrupt env-var
52
+ # names, comments, and any value that legitimately contains $OLD.
53
+ CFG="$NEW_DIR/config.yaml"
54
+ if [ -f "$CFG" ]; then
55
+ sed "${SED_INPLACE[@]}" "s|^agent: $FN/$OLD$|agent: $FN/$NEW|" "$CFG"
56
+ fi
57
+
58
+ while IFS= read -r f; do
59
+ case "$f" in
60
+ *"_archive/"*) continue ;;
61
+ *"/logs/"*) continue ;;
62
+ *"/log/runs/"*) continue ;;
63
+ *"/log/feedback/"*) continue ;;
64
+ *"/playbook/"*) continue ;;
65
+ *) sed "${SED_INPLACE[@]}" "s|$FN/$OLD|$FN/$NEW|g" "$f" ;;
66
+ esac
67
+ done < <(grep -rl "$FN/$OLD" --include='*.md' --include='*.yaml' --include='*.json' --include='*.sh' --include='*.txt' "$ROOT" 2>/dev/null)
68
+
69
+ OLD_CMD="$ROOT/.claude/commands/$OLD.md"
70
+ NEW_CMD="$ROOT/.claude/commands/$NEW.md"
71
+ if [ -f "$OLD_CMD" ]; then
72
+ mv "$OLD_CMD" "$NEW_CMD"
73
+ sed "${SED_INPLACE[@]}" "s|$OLD|$NEW|g" "$NEW_CMD"
74
+ echo " Renamed slash command: .claude/commands/$OLD.md → $NEW.md"
75
+ fi
76
+
77
+ LOG_DIR="$ROOT/chief-of-staff/logs/$(date +%Y-%m)"
78
+ mkdir -p "$LOG_DIR"
79
+ LOG_FILE="$LOG_DIR/operations-$(date +%Y-%m-%d).md"
80
+ {
81
+ echo ""
82
+ echo "## $TIMESTAMP — rename-agent: $FN/$OLD → $FN/$NEW"
83
+ } >> "$LOG_FILE"
84
+
85
+ echo ""
86
+ echo "Files mentioning '$OLD' that were NOT auto-updated (review manually):"
87
+ grep -rln "$OLD" "$ROOT" 2>/dev/null | grep -v "_archive\|/logs/\|/log/runs/\|/log/feedback/\|/playbook/" | sed "s|$ROOT/| - |" || echo " (none found)"
88
+
89
+ echo ""
90
+ echo "✓ Rename complete."
91
+ echo " Operation log: $LOG_FILE"
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env bash
2
+ # save-state.sh — write workspace state.md
3
+ #
4
+ # In v1, workspace = project. state.md lives at workspace root.
5
+ # Format: see conventions.md § "State file format". Normally Claude writes
6
+ # state.md directly when asked. This script exists for external invocation
7
+ # or scripted updates.
8
+ #
9
+ # Usage: bash scripts/save-state.sh "<state notes (multiline OK)>"
10
+
11
+ set -euo pipefail
12
+
13
+ if [ $# -lt 1 ]; then
14
+ echo "Usage: $0 \"<state notes>\""
15
+ exit 1
16
+ fi
17
+
18
+ NOTES="$*"
19
+ ROOT="$(cd "$(dirname "$0")/.." && pwd)"
20
+ STATE_FILE="$ROOT/state.md"
21
+ TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
22
+
23
+ cat > "$STATE_FILE" << EOF
24
+ ---
25
+ updated: $TIMESTAMP
26
+ ---
27
+
28
+ $NOTES
29
+ EOF
30
+
31
+ echo "✓ Saved workspace state"
32
+ echo " $STATE_FILE"