@firatcand/roster 0.4.0 → 1.0.1
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.
- package/README.md +79 -219
- package/agents/lesson-drafter.md +3 -8
- package/agents/pattern-detector.md +0 -1
- package/bin/roster.js +1407 -217
- package/package.json +2 -3
- package/skills/chief-of-staff/SKILL.md +62 -78
- package/skills/dreamer/SKILL.md +8 -7
- package/skills/roster-orchestrator/SKILL.md +53 -25
- package/templates/CLAUDE.project.template.md +1 -1
- package/templates/CONTEXT.template.md +2 -2
- package/templates/gitignore-defaults.txt +2 -0
- package/templates/scaffold/chief-of-staff/README.md +16 -24
- package/templates/scaffold/chief-of-staff/agent.md +22 -32
- package/templates/scaffold/chief-of-staff/plans/audit-agent.yaml +4 -4
- package/templates/scaffold/chief-of-staff/plans/audit-repo.yaml +5 -4
- package/templates/scaffold/chief-of-staff/plans/create-agent.yaml +5 -34
- package/templates/scaffold/config/project.yaml.template +10 -0
- package/templates/scaffold/conventions.md +159 -171
- package/templates/scaffold/dreamer/README.md +2 -2
- package/templates/scaffold/dreamer/agent.md +0 -1
- package/templates/scaffold/dreamer/plans/nightly-reflection.yaml +23 -37
- package/templates/scaffold/dreamer/subagents/lesson-drafter.md +2 -7
- package/templates/scaffold/{projects/_demo/guidelines → guidelines}/asset-links.md +4 -0
- package/templates/scaffold/{projects/_demo/guidelines → guidelines}/brand-book.md +4 -0
- package/templates/scaffold/{projects/_demo/guidelines → guidelines}/messaging.md +4 -0
- package/templates/scaffold/{projects/_demo/guidelines → guidelines}/voice.md +4 -0
- package/templates/scaffold/scripts/audit-agent.sh +74 -47
- package/templates/scaffold/scripts/audit-repo.sh +27 -49
- package/templates/scaffold/scripts/create-function.sh +1 -1
- package/templates/scaffold/scripts/lib/README.md +1 -1
- package/templates/scaffold/scripts/lib/bindings-prompt.sh +43 -124
- package/templates/scaffold/scripts/new-agent.sh +99 -91
- package/templates/scaffold/scripts/rename-agent.sh +91 -0
- package/templates/scaffold/scripts/save-state.sh +32 -0
- package/agents/critic.md +0 -74
- package/agents/enricher.md +0 -56
- package/agents/promotion-arbiter.md +0 -71
- package/agents/prospector.md +0 -51
- package/agents/writer.md +0 -58
- package/skills/sdr/SKILL.md +0 -147
- package/templates/scaffold/chief-of-staff/plans/add-agent-to-project.yaml +0 -45
- package/templates/scaffold/chief-of-staff/plans/archive-project.yaml +0 -51
- package/templates/scaffold/chief-of-staff/plans/audit-project.yaml +0 -34
- package/templates/scaffold/chief-of-staff/plans/create-project.yaml +0 -65
- package/templates/scaffold/chief-of-staff/plans/remove-agent-from-project.yaml +0 -50
- package/templates/scaffold/chief-of-staff/plans/rename-project.yaml +0 -62
- package/templates/scaffold/chief-of-staff/plans/unarchive-project.yaml +0 -41
- package/templates/scaffold/dreamer/subagents/promotion-arbiter.md +0 -64
- package/templates/scaffold/gtm/sdr/.claude/settings.json +0 -3
- package/templates/scaffold/gtm/sdr/.mcp.json +0 -21
- package/templates/scaffold/gtm/sdr/README.md +0 -41
- package/templates/scaffold/gtm/sdr/agent.md +0 -136
- package/templates/scaffold/gtm/sdr/plans/cold-outreach.yaml +0 -92
- package/templates/scaffold/gtm/sdr/projects/_demo/asset-references.md +0 -7
- package/templates/scaffold/gtm/sdr/projects/_demo/config/default.yaml +0 -69
- package/templates/scaffold/gtm/sdr/projects/_demo/log/feedback/.gitkeep +0 -0
- package/templates/scaffold/gtm/sdr/projects/_demo/log/runs/.gitkeep +0 -0
- package/templates/scaffold/gtm/sdr/projects/_demo/playbook/.gitkeep +0 -0
- package/templates/scaffold/gtm/sdr/subagents/critic.md +0 -67
- package/templates/scaffold/gtm/sdr/subagents/enricher.md +0 -49
- package/templates/scaffold/gtm/sdr/subagents/prospector.md +0 -44
- package/templates/scaffold/gtm/sdr/subagents/writer.md +0 -51
- package/templates/scaffold/projects/_demo/CLAUDE.md +0 -35
- package/templates/scaffold/projects/_demo/README.md +0 -16
- package/templates/scaffold/projects/_demo/assets/.gitkeep +0 -0
- package/templates/scaffold/projects/_demo/config/default.yaml +0 -28
- package/templates/scaffold/projects/_demo/state.md +0 -11
- package/templates/scaffold/scripts/archive-project.sh +0 -98
- package/templates/scaffold/scripts/audit-project.sh +0 -361
- package/templates/scaffold/scripts/new-agent-instance.sh +0 -114
- package/templates/scaffold/scripts/new-project.sh +0 -125
- package/templates/scaffold/scripts/remove-agent-from-project.sh +0 -67
- package/templates/scaffold/scripts/rename-project.sh +0 -118
- package/templates/scaffold/scripts/unarchive-project.sh +0 -115
- /package/templates/scaffold/gtm/{sdr/playbook/.gitkeep → .gitkeep} +0 -0
- /package/templates/scaffold/{projects/_demo/guidelines → guidelines}/icps/_persona-template.md +0 -0
|
@@ -9,7 +9,7 @@ Cross-domain pattern detection matters. A lesson observed in Twitter automation
|
|
|
9
9
|
## Files
|
|
10
10
|
|
|
11
11
|
- `agent.md` — orchestrator contract
|
|
12
|
-
- `subagents/` — pattern-detector, lesson-drafter
|
|
12
|
+
- `subagents/` — pattern-detector, lesson-drafter
|
|
13
13
|
- `playbook/` — the dreamer's own lessons (lessons about how to learn)
|
|
14
14
|
- `logs/` — its own runs
|
|
15
15
|
- `state.md` — last processed cutoff
|
|
@@ -17,7 +17,7 @@ Cross-domain pattern detection matters. A lesson observed in Twitter automation
|
|
|
17
17
|
|
|
18
18
|
## Invocation
|
|
19
19
|
|
|
20
|
-
Nightly via the native desktop scheduler. Register with `roster schedule install` — each fire spawns a fresh CLI session in the workspace, loads `CONTEXT.md`, invokes the `roster-orchestrator` skill, and dispatches the dreamer in isolated subagent context. See `conventions.md` § Schedules
|
|
20
|
+
Nightly via the native desktop scheduler. Register with `roster schedule install` — each fire spawns a fresh CLI session in the workspace, loads `CONTEXT.md`, invokes the `roster-orchestrator` skill, and dispatches the dreamer in isolated subagent context. See `conventions.md` § Schedules for the model.
|
|
21
21
|
|
|
22
22
|
On-demand from a session: "Run the dreamer on the last week's outreach runs across all projects."
|
|
23
23
|
|
|
@@ -45,7 +45,6 @@ Typically scheduled nightly via cron or `/schedule`. When invoked without a plan
|
|
|
45
45
|
|
|
46
46
|
- `pattern-detector.md` — finds patterns across runs+feedback
|
|
47
47
|
- `lesson-drafter.md` — drafts a single lesson in schema format
|
|
48
|
-
- `promotion-arbiter.md` — decides project vs global scope for validated lessons
|
|
49
48
|
|
|
50
49
|
## Tools and bindings
|
|
51
50
|
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
plan: nightly-reflection
|
|
2
2
|
description: |
|
|
3
|
-
Reads runs and feedback across all agents
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
pattern is observed in 2+ projects. Updates dreamer/state.md with the new
|
|
8
|
-
cutoff and a summary.
|
|
3
|
+
Reads runs and feedback across all agents since the last cutoff, detects
|
|
4
|
+
patterns, drafts lesson candidates, surfaces them for HITL approval via
|
|
5
|
+
Slack #admin, and writes approved lessons to each agent's playbook.
|
|
6
|
+
Updates dreamer/state.md with the new cutoff and a summary.
|
|
9
7
|
|
|
10
8
|
inputs:
|
|
11
9
|
mode:
|
|
@@ -14,7 +12,7 @@ inputs:
|
|
|
14
12
|
description: nightly | weekly | on-demand. Selects how aggressively to scan and how to weight evidence.
|
|
15
13
|
scope:
|
|
16
14
|
required: false
|
|
17
|
-
description: Limit to one
|
|
15
|
+
description: Limit to one agent (function/agent) — useful for on-demand runs.
|
|
18
16
|
since:
|
|
19
17
|
required: false
|
|
20
18
|
description: ISO timestamp cutoff. If omitted, uses last_processed_through from dreamer/state.md.
|
|
@@ -24,7 +22,6 @@ outputs:
|
|
|
24
22
|
candidates_drafted: integer
|
|
25
23
|
candidates_approved: integer
|
|
26
24
|
lessons_written: integer
|
|
27
|
-
lessons_promoted: integer
|
|
28
25
|
conflicts_surfaced: integer
|
|
29
26
|
|
|
30
27
|
steps:
|
|
@@ -35,9 +32,9 @@ steps:
|
|
|
35
32
|
|
|
36
33
|
- id: identify_material
|
|
37
34
|
description: |
|
|
38
|
-
Walk every agent's <function>/<agent>/
|
|
39
|
-
|
|
40
|
-
|
|
35
|
+
Walk every agent's <function>/<agent>/log/runs/<YYYY-MM>/ and
|
|
36
|
+
log/feedback/<YYYY-MM>/ for files newer than the cutoff. Match runs to
|
|
37
|
+
feedback by filename. Apply ${inputs.scope} filter if provided.
|
|
41
38
|
|
|
42
39
|
- id: detect_patterns
|
|
43
40
|
subagent: pattern-detector
|
|
@@ -62,52 +59,41 @@ steps:
|
|
|
62
59
|
description: |
|
|
63
60
|
For each candidate that meets threshold or extends an existing lesson,
|
|
64
61
|
draft a lesson in schema format with frontmatter (id, source: dreamer,
|
|
65
|
-
|
|
66
|
-
|
|
62
|
+
status: candidate, agent, created). Place drafts in
|
|
63
|
+
<function>/<agent>/pending/.
|
|
67
64
|
args:
|
|
68
65
|
input_from: accumulate_evidence
|
|
69
66
|
|
|
70
|
-
- id: arbitrate_promotion
|
|
71
|
-
subagent: promotion-arbiter
|
|
72
|
-
description: |
|
|
73
|
-
For any project lesson validated in 2+ projects, decide whether to
|
|
74
|
-
promote to global scope. Returns project vs global designation per
|
|
75
|
-
candidate.
|
|
76
|
-
args:
|
|
77
|
-
input_from: draft_lessons
|
|
78
|
-
|
|
79
67
|
- id: hitl_routing
|
|
80
68
|
description: |
|
|
81
|
-
Post all candidates
|
|
69
|
+
Post all candidates to Slack #admin (channel from
|
|
82
70
|
SLACK_HITL_CHANNEL_ADMIN env var) as threaded messages, one per
|
|
83
71
|
candidate. Format: "Candidate lesson <id>: <title>. Approve / Reject /
|
|
84
72
|
Defer." TTL 7 days. If Slack unavailable, queue candidates locally in
|
|
85
|
-
|
|
73
|
+
<function>/<agent>/pending/ and retry next run.
|
|
86
74
|
approval: slack
|
|
87
75
|
|
|
88
76
|
- id: apply_approvals
|
|
89
77
|
description: |
|
|
90
|
-
On approval,
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
Respect human-written lessons (source: human) — never modify or
|
|
98
|
-
supersede without explicit HITL approval.
|
|
78
|
+
On approval, move the candidate file from <function>/<agent>/pending/
|
|
79
|
+
to <function>/<agent>/playbook/L-...md. There is no scope decision;
|
|
80
|
+
v1 has a single playbook per agent. All dreamer-written lessons get
|
|
81
|
+
source: dreamer in frontmatter. Respect human-written lessons
|
|
82
|
+
(source: human) — never modify or supersede without explicit HITL
|
|
83
|
+
approval. Retired candidates update an existing lesson's status:
|
|
84
|
+
retired with reason.
|
|
99
85
|
|
|
100
86
|
- id: update_state
|
|
101
87
|
description: |
|
|
102
88
|
Write timestamp + summary to dreamer/state.md:
|
|
103
89
|
last_processed_through: <ISO timestamp>
|
|
104
|
-
last_run_summary: drafted N, approved M, written K
|
|
90
|
+
last_run_summary: drafted N, approved M, written K
|
|
105
91
|
|
|
106
92
|
- id: write_run_log
|
|
107
93
|
description: |
|
|
108
94
|
Write run details to dreamer/logs/<YYYY-MM>/<YYYY-MM-DD-HHMM>.md
|
|
109
|
-
including: material processed (counts by
|
|
110
|
-
|
|
111
|
-
|
|
95
|
+
including: material processed (counts by agent), patterns detected,
|
|
96
|
+
lesson candidates drafted (Slack thread links), approvals applied,
|
|
97
|
+
conflicts surfaced.
|
|
112
98
|
|
|
113
99
|
approval_channel: slack
|
|
@@ -9,20 +9,17 @@ Take a candidate pattern and draft a lesson file in the schema defined in `conve
|
|
|
9
9
|
- `pattern` (object): output from pattern-detector
|
|
10
10
|
- `existing_lesson` (object, optional): if extending an existing lesson, the current version
|
|
11
11
|
- `agent` (string): which agent
|
|
12
|
-
- `project` (string): which project sourced it
|
|
13
12
|
|
|
14
13
|
## Output
|
|
15
14
|
|
|
16
15
|
```yaml
|
|
17
16
|
suggested_filename: L-2026-04-26-001.md
|
|
18
|
-
suggested_path: <function>/<agent>/
|
|
17
|
+
suggested_path: <function>/<agent>/playbook/
|
|
19
18
|
status: candidate
|
|
20
19
|
lesson_markdown: |
|
|
21
20
|
---
|
|
22
21
|
id: L-2026-04-26-001
|
|
23
22
|
source: dreamer
|
|
24
|
-
scope: project # or global
|
|
25
|
-
project: _demo # or "—" if scope=global
|
|
26
23
|
agent: sdr
|
|
27
24
|
...full frontmatter per conventions...
|
|
28
25
|
---
|
|
@@ -31,7 +28,6 @@ lesson_markdown: |
|
|
|
31
28
|
|
|
32
29
|
## Pattern observed
|
|
33
30
|
## Recommendation
|
|
34
|
-
## Why this might be project-specific
|
|
35
31
|
## Retirement criteria
|
|
36
32
|
```
|
|
37
33
|
|
|
@@ -43,9 +39,8 @@ None.
|
|
|
43
39
|
|
|
44
40
|
- Use the exact schema in `conventions.md`. Don't invent fields.
|
|
45
41
|
- Always set `source: dreamer`.
|
|
46
|
-
- Default to `scope: project` unless explicitly handling a promotion case.
|
|
47
42
|
- Cite evidence in body, not just frontmatter.
|
|
48
|
-
- Body has
|
|
43
|
+
- Body has 3 sections: pattern, recommendation, retirement criteria. That's it.
|
|
49
44
|
|
|
50
45
|
## Quality bar
|
|
51
46
|
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
> **Example content — replace with your project's actuals.**
|
|
2
|
+
> This file ships filled with an illustrative brand ("Acme Corp") so you can
|
|
3
|
+
> see the expected shape. Overwrite freely; no agent will warn if you do.
|
|
4
|
+
|
|
1
5
|
# Messaging — Acme Corp
|
|
2
6
|
|
|
3
7
|
## Headline value props
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
> **Example content — replace with your project's actuals.**
|
|
2
|
+
> This file ships filled with an illustrative brand ("Acme Corp") so you can
|
|
3
|
+
> see the expected shape. Overwrite freely; no agent will warn if you do.
|
|
4
|
+
|
|
1
5
|
# Voice — Acme Corp
|
|
2
6
|
|
|
3
7
|
## Adjectives describing the brand voice
|
|
@@ -42,7 +42,7 @@ PASSED=()
|
|
|
42
42
|
if [ ! -f "$AGENT_DIR/agent.md" ]; then
|
|
43
43
|
FAILURES+=("[$FN/$AGENT/agent.md] missing")
|
|
44
44
|
else
|
|
45
|
-
REQUIRED_SECTIONS=("## Purpose" "## Inputs" "## Plans" "## Subagents" "##
|
|
45
|
+
REQUIRED_SECTIONS=("## Purpose" "## Inputs" "## Plans" "## Subagents" "## Outputs" "## Approval" "## Lessons protocol")
|
|
46
46
|
MISSING=()
|
|
47
47
|
for section in "${REQUIRED_SECTIONS[@]}"; do
|
|
48
48
|
if ! grep -qF "$section" "$AGENT_DIR/agent.md"; then
|
|
@@ -56,6 +56,14 @@ else
|
|
|
56
56
|
PASSED+=("[$FN/$AGENT/agent.md] all required sections present")
|
|
57
57
|
fi
|
|
58
58
|
|
|
59
|
+
# ## Tools and bindings is required ONLY for agents that use external tools.
|
|
60
|
+
# Missing → warning, not failure (agents reading only workspace guidelines
|
|
61
|
+
# don't need it). The chief-of-staff create-agent guided flow adds the
|
|
62
|
+
# section when the user names tools.
|
|
63
|
+
if ! grep -qF "## Tools and bindings" "$AGENT_DIR/agent.md"; then
|
|
64
|
+
WARNINGS+=("[$FN/$AGENT/agent.md] '## Tools and bindings' not declared — fine for tool-less agents; required if this agent calls external APIs")
|
|
65
|
+
fi
|
|
66
|
+
|
|
59
67
|
# Steps section should NOT be present anymore — workflows live in plans/
|
|
60
68
|
if grep -qE '^## Steps' "$AGENT_DIR/agent.md"; then
|
|
61
69
|
WARNINGS+=("[$FN/$AGENT/agent.md] still has a '## Steps' section — workflow logic should live in plans/<plan>.yaml, not agent.md")
|
|
@@ -105,6 +113,62 @@ else
|
|
|
105
113
|
PASSED+=("[$FN/$AGENT/README.md] present")
|
|
106
114
|
fi
|
|
107
115
|
|
|
116
|
+
# config.yaml — agent config (guideline refs + tool bindings).
|
|
117
|
+
# Schema check: single-document mapping with agent=$FN/$AGENT, plans_dir,
|
|
118
|
+
# guideline_refs (mapping), tools (mapping). Drift here breaks the runtime
|
|
119
|
+
# loader (Phase 2) and `chief-of-staff create-agent` reuse.
|
|
120
|
+
if [ ! -f "$AGENT_DIR/config.yaml" ]; then
|
|
121
|
+
FAILURES+=("[$FN/$AGENT/config.yaml] missing")
|
|
122
|
+
FAILURES+=(" → Suggested fix: add config.yaml at agent root with at least 'agent: $FN/$AGENT' and 'plans_dir: ./plans/'")
|
|
123
|
+
elif command -v python3 >/dev/null 2>&1; then
|
|
124
|
+
CFG_RC=0
|
|
125
|
+
CFG_MSG="$(AGENT_EXPECT="$FN/$AGENT" CFG_PATH="$AGENT_DIR/config.yaml" python3 - <<'PYEOF' 2>&1
|
|
126
|
+
import os, sys
|
|
127
|
+
try:
|
|
128
|
+
import yaml
|
|
129
|
+
except ImportError:
|
|
130
|
+
sys.stderr.write("pyyaml-missing")
|
|
131
|
+
sys.exit(2)
|
|
132
|
+
expect = os.environ["AGENT_EXPECT"]
|
|
133
|
+
path = os.environ["CFG_PATH"]
|
|
134
|
+
with open(path) as f:
|
|
135
|
+
try:
|
|
136
|
+
doc = yaml.safe_load(f)
|
|
137
|
+
except yaml.YAMLError as e:
|
|
138
|
+
sys.stderr.write(f"yaml-parse-error: {e}")
|
|
139
|
+
sys.exit(1)
|
|
140
|
+
if not isinstance(doc, dict):
|
|
141
|
+
sys.stderr.write("not-a-mapping")
|
|
142
|
+
sys.exit(1)
|
|
143
|
+
errs = []
|
|
144
|
+
agent = doc.get("agent")
|
|
145
|
+
if agent != expect:
|
|
146
|
+
errs.append(f"agent field is {agent!r}, expected {expect!r}")
|
|
147
|
+
if "plans_dir" not in doc:
|
|
148
|
+
errs.append("missing plans_dir")
|
|
149
|
+
gr = doc.get("guideline_refs")
|
|
150
|
+
if gr is not None and not isinstance(gr, dict):
|
|
151
|
+
errs.append("guideline_refs is not a mapping")
|
|
152
|
+
tools = doc.get("tools")
|
|
153
|
+
if tools is not None and not isinstance(tools, dict):
|
|
154
|
+
errs.append("tools is not a mapping")
|
|
155
|
+
if errs:
|
|
156
|
+
sys.stderr.write("; ".join(errs))
|
|
157
|
+
sys.exit(1)
|
|
158
|
+
PYEOF
|
|
159
|
+
)" || CFG_RC=$?
|
|
160
|
+
if [ $CFG_RC -eq 0 ]; then
|
|
161
|
+
PASSED+=("[$FN/$AGENT/config.yaml] valid (schema)")
|
|
162
|
+
elif [ $CFG_RC -eq 2 ]; then
|
|
163
|
+
PASSED+=("[$FN/$AGENT/config.yaml] present (schema not validated, pyyaml missing)")
|
|
164
|
+
else
|
|
165
|
+
FAILURES+=("[$FN/$AGENT/config.yaml] $CFG_MSG")
|
|
166
|
+
FAILURES+=(" → Suggested fix: open the file and ensure it is a single YAML mapping with 'agent: $FN/$AGENT', 'plans_dir', a 'guideline_refs:' mapping, and a 'tools:' mapping (may be empty)")
|
|
167
|
+
fi
|
|
168
|
+
else
|
|
169
|
+
PASSED+=("[$FN/$AGENT/config.yaml] present (schema not validated, python3 missing)")
|
|
170
|
+
fi
|
|
171
|
+
|
|
108
172
|
# .mcp.json valid JSON
|
|
109
173
|
if [ ! -f "$AGENT_DIR/.mcp.json" ]; then
|
|
110
174
|
WARNINGS+=("[$FN/$AGENT/.mcp.json] missing (no agent-scoped MCPs configured)")
|
|
@@ -168,53 +232,18 @@ else
|
|
|
168
232
|
PASSED+=("[$FN/$AGENT/playbook/] present")
|
|
169
233
|
fi
|
|
170
234
|
|
|
171
|
-
#
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
else
|
|
176
|
-
PASSED+=("[$FN/$AGENT/projects/_template/] present")
|
|
177
|
-
fi
|
|
178
|
-
|
|
179
|
-
# === Each instance ===
|
|
180
|
-
INSTANCES=()
|
|
181
|
-
while IFS= read -r path; do
|
|
182
|
-
INSTANCES+=("$path")
|
|
183
|
-
done < <(find "$AGENT_DIR/projects" -maxdepth 1 -mindepth 1 -type d -not -name '_template' 2>/dev/null || true)
|
|
184
|
-
|
|
185
|
-
for inst in "${INSTANCES[@]}"; do
|
|
186
|
-
REL="${inst#$ROOT/}"
|
|
187
|
-
PROJECT_NAME=$(basename "$inst")
|
|
188
|
-
|
|
189
|
-
CONFIG="$inst/config/default.yaml"
|
|
190
|
-
if [ ! -f "$CONFIG" ]; then
|
|
191
|
-
FAILURES+=("[$REL/config/default.yaml] missing")
|
|
192
|
-
else
|
|
193
|
-
if command -v python3 >/dev/null 2>&1; then
|
|
194
|
-
if ! python3 -c "import yaml; list(yaml.safe_load_all(open('$CONFIG')))" 2>/dev/null; then
|
|
195
|
-
FAILURES+=("[$REL/config/default.yaml] YAML parse error")
|
|
196
|
-
else
|
|
197
|
-
DECLARED=$(python3 -c "import yaml; docs = list(yaml.safe_load_all(open('$CONFIG'))); print((docs[0] or {}).get('project', ''))" 2>/dev/null || echo "")
|
|
198
|
-
if [ "$DECLARED" != "$PROJECT_NAME" ]; then
|
|
199
|
-
FAILURES+=("[$REL/config/default.yaml] project field '$DECLARED' doesn't match folder '$PROJECT_NAME'")
|
|
200
|
-
else
|
|
201
|
-
PASSED+=("[$REL/config/default.yaml] valid")
|
|
202
|
-
fi
|
|
203
|
-
fi
|
|
204
|
-
fi
|
|
205
|
-
fi
|
|
206
|
-
|
|
207
|
-
for d in log/runs log/feedback playbook; do
|
|
208
|
-
if [ ! -d "$inst/$d" ]; then
|
|
209
|
-
WARNINGS+=("[$REL/$d/] missing")
|
|
210
|
-
fi
|
|
211
|
-
done
|
|
212
|
-
|
|
213
|
-
if [ ! -f "$inst/asset-references.md" ]; then
|
|
214
|
-
WARNINGS+=("[$REL/asset-references.md] missing")
|
|
235
|
+
# Flat-shape directories
|
|
236
|
+
for d in logs/runs logs/feedback pending; do
|
|
237
|
+
if [ ! -d "$AGENT_DIR/$d" ]; then
|
|
238
|
+
WARNINGS+=("[$FN/$AGENT/$d/] missing")
|
|
215
239
|
fi
|
|
216
240
|
done
|
|
217
241
|
|
|
242
|
+
# asset-references.md at agent root
|
|
243
|
+
if [ ! -f "$AGENT_DIR/asset-references.md" ]; then
|
|
244
|
+
WARNINGS+=("[$FN/$AGENT/asset-references.md] missing")
|
|
245
|
+
fi
|
|
246
|
+
|
|
218
247
|
# === Status ===
|
|
219
248
|
if [ ${#FAILURES[@]} -gt 0 ]; then
|
|
220
249
|
STATUS="fail"
|
|
@@ -265,7 +294,6 @@ N_PASS=${#PASSED[@]}
|
|
|
265
294
|
echo "- $N_PASS passed"
|
|
266
295
|
echo "- $N_WARN warnings"
|
|
267
296
|
echo "- $N_FAIL failures"
|
|
268
|
-
echo "- ${#INSTANCES[@]} instance(s) audited"
|
|
269
297
|
echo ""
|
|
270
298
|
if [ $N_FAIL -gt 0 ]; then
|
|
271
299
|
echo "## Failures"
|
|
@@ -291,7 +319,6 @@ N_PASS=${#PASSED[@]}
|
|
|
291
319
|
|
|
292
320
|
echo "Audit: $FN/$AGENT — $STATUS"
|
|
293
321
|
echo " Passed: $N_PASS, Warnings: $N_WARN, Failures: $N_FAIL"
|
|
294
|
-
echo " Instances audited: ${#INSTANCES[@]}"
|
|
295
322
|
[ $N_FAIL -gt 0 ] && {
|
|
296
323
|
echo "Failures:"
|
|
297
324
|
for line in "${FAILURES[@]}"; do echo " $line"; done
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# audit-repo.sh — full
|
|
2
|
+
# audit-repo.sh — full workspace audit; runs agent audits and repo-level checks
|
|
3
3
|
# Usage: bash scripts/audit-repo.sh
|
|
4
4
|
|
|
5
5
|
set -euo pipefail
|
|
@@ -51,30 +51,34 @@ for f in CLAUDE.md conventions.md README.md; do
|
|
|
51
51
|
fi
|
|
52
52
|
done
|
|
53
53
|
|
|
54
|
-
#
|
|
55
|
-
|
|
54
|
+
# config/project.yaml — workspace identity (v1 shape)
|
|
55
|
+
if [ ! -f "$ROOT/config/project.yaml" ]; then
|
|
56
|
+
REPO_FAILURES+=("[config/project.yaml] missing — workspace identity required")
|
|
57
|
+
elif command -v python3 >/dev/null 2>&1; then
|
|
58
|
+
if ! python3 -c "import yaml; yaml.safe_load(open('$ROOT/config/project.yaml'))" 2>/dev/null; then
|
|
59
|
+
REPO_FAILURES+=("[config/project.yaml] YAML parse error")
|
|
60
|
+
else
|
|
61
|
+
REPO_PASSED+=("[config/project.yaml] valid")
|
|
62
|
+
fi
|
|
63
|
+
fi
|
|
56
64
|
|
|
57
|
-
#
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
# We only care about instances: <fn>/<agent>/projects/<proj>/ where agent.md is missing
|
|
66
|
-
GRANDPARENT=$(dirname "$PARENT")
|
|
67
|
-
GP_NAME=$(basename "$GRANDPARENT")
|
|
68
|
-
if [ -n "$REGISTERED_FNS_PIPE" ] && echo "$GP_NAME" | grep -qE "^($REGISTERED_FNS_PIPE)\$"; then
|
|
69
|
-
echo "$p"
|
|
65
|
+
# guidelines/ — cross-agent substrate
|
|
66
|
+
if [ ! -d "$ROOT/guidelines" ]; then
|
|
67
|
+
REPO_FAILURES+=("[guidelines/] missing — workspace substrate dir required")
|
|
68
|
+
else
|
|
69
|
+
REPO_PASSED+=("[guidelines/] present")
|
|
70
|
+
for f in voice.md messaging.md brand-book.md asset-links.md; do
|
|
71
|
+
if [ ! -f "$ROOT/guidelines/$f" ]; then
|
|
72
|
+
REPO_WARNINGS+=("[guidelines/$f] missing — required substrate file")
|
|
70
73
|
fi
|
|
74
|
+
done
|
|
75
|
+
if [ ! -d "$ROOT/guidelines/icps" ] || [ -z "$(find "$ROOT/guidelines/icps" -maxdepth 1 -name '*.md' -type f 2>/dev/null | head -1)" ]; then
|
|
76
|
+
REPO_WARNINGS+=("[guidelines/icps/] empty or missing — at least one persona file required")
|
|
71
77
|
fi
|
|
72
|
-
|
|
78
|
+
fi
|
|
73
79
|
|
|
74
|
-
for
|
|
75
|
-
|
|
76
|
-
REPO_WARNINGS+=("[$REL] orphaned instance — parent agent has no agent.md")
|
|
77
|
-
done
|
|
80
|
+
# Build a regex of registered functions for matching grandparent dirs.
|
|
81
|
+
REGISTERED_FNS_PIPE=$(read_functions 2>/dev/null | tr '\n' '|' | sed 's/|$//')
|
|
78
82
|
|
|
79
83
|
# Registered function should have a folder
|
|
80
84
|
while IFS= read -r fn; do
|
|
@@ -109,7 +113,7 @@ if [ -f "$ENV_EXAMPLE" ]; then
|
|
|
109
113
|
fi
|
|
110
114
|
|
|
111
115
|
# Function-shaped top-level dirs not in the registry
|
|
112
|
-
KNOWN_NON_FUNCTIONS="dreamer chief-of-staff
|
|
116
|
+
KNOWN_NON_FUNCTIONS="dreamer chief-of-staff scripts logs _archive"
|
|
113
117
|
for dir in "$ROOT"/*/; do
|
|
114
118
|
basename=$(basename "$dir")
|
|
115
119
|
[[ "$basename" == .* ]] && continue
|
|
@@ -123,25 +127,6 @@ for dir in "$ROOT"/*/; do
|
|
|
123
127
|
fi
|
|
124
128
|
done
|
|
125
129
|
|
|
126
|
-
# === Run audit-project for each project ===
|
|
127
|
-
PROJECTS=()
|
|
128
|
-
while IFS= read -r path; do
|
|
129
|
-
PROJECTS+=("$path")
|
|
130
|
-
done < <(find "$ROOT/projects" -maxdepth 1 -mindepth 1 -type d -not -name '_template' 2>/dev/null || true)
|
|
131
|
-
|
|
132
|
-
PROJECT_RESULTS=()
|
|
133
|
-
for proj_path in "${PROJECTS[@]:-}"; do
|
|
134
|
-
PROJ=$(basename "$proj_path")
|
|
135
|
-
RESULT=$(bash "$ROOT/scripts/audit-project.sh" "$PROJ" 2>&1 | head -5 || echo " (audit failed)")
|
|
136
|
-
PROJECT_RESULTS+=("### $PROJ")
|
|
137
|
-
PROJECT_RESULTS+=("\`\`\`")
|
|
138
|
-
while IFS= read -r line; do
|
|
139
|
-
PROJECT_RESULTS+=("$line")
|
|
140
|
-
done <<< "$RESULT"
|
|
141
|
-
PROJECT_RESULTS+=("\`\`\`")
|
|
142
|
-
PROJECT_RESULTS+=("")
|
|
143
|
-
done
|
|
144
|
-
|
|
145
130
|
# === Run audit-agent for each agent ===
|
|
146
131
|
AGENTS=()
|
|
147
132
|
while IFS= read -r fn; do
|
|
@@ -187,7 +172,6 @@ fi
|
|
|
187
172
|
echo "# Repo Audit"
|
|
188
173
|
echo ""
|
|
189
174
|
echo "## Summary"
|
|
190
|
-
echo "- Projects audited: ${#PROJECTS[@]}"
|
|
191
175
|
echo "- Agents audited: ${#AGENTS[@]}"
|
|
192
176
|
echo "- Repo-level passed: ${#REPO_PASSED[@]}"
|
|
193
177
|
echo "- Repo-level warnings: ${#REPO_WARNINGS[@]}"
|
|
@@ -214,12 +198,6 @@ fi
|
|
|
214
198
|
done
|
|
215
199
|
echo ""
|
|
216
200
|
fi
|
|
217
|
-
echo "## Project audits (summaries)"
|
|
218
|
-
echo ""
|
|
219
|
-
for line in "${PROJECT_RESULTS[@]:-}"; do
|
|
220
|
-
echo "$line"
|
|
221
|
-
done
|
|
222
|
-
echo ""
|
|
223
201
|
echo "## Agent audits (summaries)"
|
|
224
202
|
echo ""
|
|
225
203
|
for line in "${AGENT_RESULTS[@]:-}"; do
|
|
@@ -231,7 +209,7 @@ fi
|
|
|
231
209
|
|
|
232
210
|
# Print summary
|
|
233
211
|
echo "Repo audit: $STATUS"
|
|
234
|
-
echo "
|
|
212
|
+
echo " Agents: ${#AGENTS[@]}"
|
|
235
213
|
echo " Repo-level: ${#REPO_PASSED[@]} passed, ${#REPO_WARNINGS[@]} warnings, ${#REPO_FAILURES[@]} failures"
|
|
236
214
|
[ ${#REPO_FAILURES[@]} -gt 0 ] && {
|
|
237
215
|
echo "Repo failures:"
|
|
@@ -215,7 +215,7 @@ if [ "$WITH_EXPERT" = "true" ]; then
|
|
|
215
215
|
This is a stub. Fill in the expert system prompt for this function.
|
|
216
216
|
|
|
217
217
|
Experts shape SUBSTRATE (project guidelines), not artifacts. They critique
|
|
218
|
-
and generate guideline files in \`
|
|
218
|
+
and generate guideline files in \`guidelines/\` at the workspace root.
|
|
219
219
|
|
|
220
220
|
Required sections (see other EXPERT.md files for examples once they exist):
|
|
221
221
|
- Identity (1 paragraph)
|
|
@@ -10,7 +10,7 @@ Conventions:
|
|
|
10
10
|
## Current inhabitants
|
|
11
11
|
|
|
12
12
|
- `functions.sh` — read/validate the function registry at `.config/functions.yaml`. Pure bash + falls back to `python3` + `pyyaml` when available for safer YAML parsing.
|
|
13
|
-
- `bindings-prompt.sh` —
|
|
13
|
+
- `bindings-prompt.sh` — **disabled in v1.0**. Phase 2 will rebuild this around the env-merge loader (config.yaml `tools:` metadata + `/.env` values). Until then, invocation aborts with manual-configuration instructions (edit agent.md `## Tools and bindings` → mirror the YAML block into `<agent>/config.yaml` → add env-var values to `/.env`). The file remains in the tarball + executable so smoke continues to assert presence; the runtime behavior is the guard message.
|
|
14
14
|
|
|
15
15
|
Example future additions:
|
|
16
16
|
- `lib/lesson.sh` — read/write lesson files, validate schema
|