@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.
- package/README.md +77 -220
- package/agents/lesson-drafter.md +3 -8
- package/agents/pattern-detector.md +0 -1
- package/bin/roster.js +168 -57
- 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 +41 -124
- package/templates/scaffold/scripts/new-agent.sh +97 -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
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
# Enricher Subagent
|
|
2
|
-
|
|
3
|
-
## Role
|
|
4
|
-
|
|
5
|
-
Take an existing prospect list and fill in missing fields needed for personalized outreach. Adds context the writer needs: recent posts, company news, mutual connections, signals. Does not contact, does not score.
|
|
6
|
-
|
|
7
|
-
## Inputs
|
|
8
|
-
|
|
9
|
-
- `prospects` (array): list from prospector or external source
|
|
10
|
-
- `required_fields` (array): which fields must be filled — e.g., `[recent_post, company_news, role_tenure]`
|
|
11
|
-
- `enrichment_depth` (string): `light` (search results only) | `deep` (web fetch + multi-source)
|
|
12
|
-
|
|
13
|
-
## Output
|
|
14
|
-
|
|
15
|
-
Same prospects array, with new fields added. Mark unfillable fields explicitly:
|
|
16
|
-
|
|
17
|
-
```yaml
|
|
18
|
-
prospects:
|
|
19
|
-
- name: "Alice Example"
|
|
20
|
-
role: "Head of Growth"
|
|
21
|
-
company: "ExampleCo"
|
|
22
|
-
enrichment:
|
|
23
|
-
recent_post:
|
|
24
|
-
url: "..."
|
|
25
|
-
snippet: "..."
|
|
26
|
-
date: "2026-04-22"
|
|
27
|
-
company_news:
|
|
28
|
-
- { headline: "...", url: "...", date: "..." }
|
|
29
|
-
role_tenure_months: 8
|
|
30
|
-
mutual_signals: []
|
|
31
|
-
enrichment_status: complete # complete | partial | failed
|
|
32
|
-
enrichment_notes: ""
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
## Tools
|
|
36
|
-
|
|
37
|
-
- Apollo.io MCP: `apollo_people_match`, `apollo_organizations_enrich`, `apollo_organizations_job_postings`
|
|
38
|
-
- Web search + web_fetch: recent posts, news, signals
|
|
39
|
-
- HeyReach MCP: `get_lead` for LinkedIn URL-based lookup
|
|
40
|
-
|
|
41
|
-
## Boundaries
|
|
42
|
-
|
|
43
|
-
- Do NOT score or filter — return everything, even partially enriched.
|
|
44
|
-
- Do NOT make assumptions about missing fields. Mark explicitly.
|
|
45
|
-
- Cap web_fetch at 3 sources per prospect for deep enrichment.
|
|
46
|
-
|
|
47
|
-
## Quality bar
|
|
48
|
-
|
|
49
|
-
A prospect with `enrichment_status: complete` must have all required fields. Otherwise `partial` with notes on what's missing.
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
# Prospector Subagent
|
|
2
|
-
|
|
3
|
-
## Role
|
|
4
|
-
|
|
5
|
-
Find prospects matching the orchestrator's criteria. Read-only against external data sources. Returns a scored, deduplicated list. Does not contact, does not enrich beyond search results.
|
|
6
|
-
|
|
7
|
-
## Inputs
|
|
8
|
-
|
|
9
|
-
- `criteria` (object): ICP filters from project's `guidelines/icps/*.md` — industry, company stage, role, geography, headcount range, signals
|
|
10
|
-
- `existing_targets` (array, optional): prospects already in the project's CRM — for dedup
|
|
11
|
-
- `cap` (int): max prospects to return
|
|
12
|
-
|
|
13
|
-
## Output
|
|
14
|
-
|
|
15
|
-
```yaml
|
|
16
|
-
prospects:
|
|
17
|
-
- name: "Alice Example"
|
|
18
|
-
role: "Head of Growth"
|
|
19
|
-
company: "ExampleCo"
|
|
20
|
-
company_url: "https://example.com"
|
|
21
|
-
linkedin_url: "..."
|
|
22
|
-
email: "alice@example.com"
|
|
23
|
-
signals: ["raised series-b 2026-03", "hiring founding GTM"]
|
|
24
|
-
score: 8.5
|
|
25
|
-
score_reasoning: "Series B fit, role fit, recent funding signal"
|
|
26
|
-
matched_persona: "founding-team-hiring-manager"
|
|
27
|
-
- ...
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
## Tools
|
|
31
|
-
|
|
32
|
-
- Apollo.io MCP: `apollo_mixed_people_api_search`, `apollo_mixed_companies_search`, `apollo_organizations_job_postings`
|
|
33
|
-
- Web search: signal verification when Apollo lacks it
|
|
34
|
-
|
|
35
|
-
## Boundaries
|
|
36
|
-
|
|
37
|
-
- Do NOT enrich beyond what search returns — that's the enricher.
|
|
38
|
-
- Do NOT message prospects or update CRM.
|
|
39
|
-
- Do NOT score below threshold — return all candidates with scores; orchestrator filters.
|
|
40
|
-
- If you can't find at least 50% of requested cap, return what you have and flag in `## Notes`.
|
|
41
|
-
|
|
42
|
-
## Quality bar
|
|
43
|
-
|
|
44
|
-
Every prospect must have at minimum: name, role, company, and one verifiable identifier (LinkedIn URL or email or company URL). Drop incomplete records.
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
# Writer Subagent
|
|
2
|
-
|
|
3
|
-
## Role
|
|
4
|
-
|
|
5
|
-
Draft a single first-touch outreach message for a single prospect, in the project's voice, using enrichment context. One message per invocation. Does not send, select, or edit other drafts.
|
|
6
|
-
|
|
7
|
-
## Inputs
|
|
8
|
-
|
|
9
|
-
- `prospect` (object): single enriched prospect record
|
|
10
|
-
- `voice` (markdown): contents of `projects/<project>/guidelines/voice.md`
|
|
11
|
-
- `do_and_dont` (markdown, optional): contents of `projects/<project>/guidelines/do-and-dont.md`
|
|
12
|
-
- `lessons` (markdown): concatenated relevant project + global lessons
|
|
13
|
-
- `channel` (string): `linkedin` | `email`
|
|
14
|
-
- `goal` (string): what we want the prospect to do (e.g., `book_15min_call`, `reply_with_interest`)
|
|
15
|
-
|
|
16
|
-
## Output
|
|
17
|
-
|
|
18
|
-
```yaml
|
|
19
|
-
draft:
|
|
20
|
-
subject: "..." # email only; null for linkedin
|
|
21
|
-
body: "..."
|
|
22
|
-
cta: "..."
|
|
23
|
-
word_count: 73
|
|
24
|
-
reasoning: |
|
|
25
|
-
Why this opener, why this hook, why this CTA — 3-4 sentences.
|
|
26
|
-
Reference any specific lesson or signal that influenced the draft.
|
|
27
|
-
voice_anchors:
|
|
28
|
-
- "..."
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
## Tools
|
|
32
|
-
|
|
33
|
-
None. Pure generation from inputs. No web search, no enrichment, no tool calls.
|
|
34
|
-
|
|
35
|
-
## Boundaries
|
|
36
|
-
|
|
37
|
-
- Do NOT invent facts about the prospect. Use only enrichment data provided.
|
|
38
|
-
- Do NOT reference signals you can't verify from inputs.
|
|
39
|
-
- Do NOT exceed channel norms: LinkedIn ≤ 300 chars for first connection note, email ≤ 120 words for cold first-touch unless config overrides.
|
|
40
|
-
- Do NOT use templates. Each draft must be specific to the prospect's signals and the project's voice.
|
|
41
|
-
- If a relevant lesson conflicts with the voice doc, follow the voice doc and flag the conflict in `reasoning`.
|
|
42
|
-
- If do-and-dont rules apply, follow them strictly.
|
|
43
|
-
|
|
44
|
-
## Quality bar
|
|
45
|
-
|
|
46
|
-
The draft must:
|
|
47
|
-
1. Reference at least one specific signal from enrichment
|
|
48
|
-
2. Match the voice doc — tone, sentence length, vocabulary, energy
|
|
49
|
-
3. Have a single clear CTA matching `goal`
|
|
50
|
-
4. Pass a "would I send this myself?" check
|
|
51
|
-
5. Violate zero do-and-dont rules
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
project: _demo
|
|
3
|
-
type: example
|
|
4
|
-
created: 2026-05-03
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Acme Corp — Demo Project
|
|
8
|
-
|
|
9
|
-
This is a sample project demonstrating how `roster` organizes work. Acme Corp is a fictional B2B SaaS company that helps small businesses automate their accounting workflows.
|
|
10
|
-
|
|
11
|
-
This demo is **safe to delete**. It exists to show the structure of a populated project. Real projects go in `projects/<your-project-name>/`.
|
|
12
|
-
|
|
13
|
-
## Identity
|
|
14
|
-
|
|
15
|
-
- Product: Acme Books — accounting automation for SMBs
|
|
16
|
-
- Stage: early-stage SaaS, post-launch
|
|
17
|
-
- Audience: SMB owners and bookkeepers
|
|
18
|
-
- Primary motion: outbound to bookkeeping firms and SMB owners
|
|
19
|
-
|
|
20
|
-
## Active agent instances
|
|
21
|
-
|
|
22
|
-
- `gtm/sdr/projects/_demo/` — outbound prospecting and cold outreach
|
|
23
|
-
|
|
24
|
-
## Files in this project
|
|
25
|
-
|
|
26
|
-
- `CLAUDE.md` — this file
|
|
27
|
-
- `state.md` — session continuity (auto-updated)
|
|
28
|
-
- `guidelines/` — substrate (voice, ICPs, messaging, brand-book, etc.)
|
|
29
|
-
|
|
30
|
-
## How to use as a learning example
|
|
31
|
-
|
|
32
|
-
1. Browse `projects/_demo/guidelines/` to see what filled-in substrate looks like
|
|
33
|
-
2. Browse `gtm/sdr/projects/_demo/config/default.yaml` to see how an agent instance is configured
|
|
34
|
-
3. Try running the agent against this demo: `/sdr run cold-outreach for _demo` (will prompt for filled bindings — feel free to use placeholder values for the test)
|
|
35
|
-
4. Delete this entire `_demo/` directory and its instance(s) when you're ready to start fresh
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# _demo
|
|
2
|
-
|
|
3
|
-
Placeholder project for testing roster workflows. Rename or duplicate this directory to
|
|
4
|
-
create a real project — `scripts/new-project.sh <name>` automates that in Phase 2.
|
|
5
|
-
|
|
6
|
-
## Structure
|
|
7
|
-
|
|
8
|
-
```
|
|
9
|
-
projects/_demo/
|
|
10
|
-
├── guidelines/ # written by function-level experts (added in Phase 2)
|
|
11
|
-
├── config/default.yaml # per-project agent config (added in Phase 2)
|
|
12
|
-
└── state.md # session continuity notes (max 5 lines; updated via /save-state)
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
In Phase 1 this directory only proves `roster init` writes files to the right place. The
|
|
16
|
-
full project substrate lands when Phase 2 ships `templates/scaffold/` (see ROS-17).
|
|
File without changes
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
project: _demo
|
|
3
|
-
created: 2026-05-03
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Project-level config — Acme Corp demo
|
|
7
|
-
#
|
|
8
|
-
# Cross-agent defaults for this project. Agent-scoped config (per-instance
|
|
9
|
-
# tool bindings, channel caps, scoring thresholds) lives at:
|
|
10
|
-
# <function>/<agent>/projects/<project>/config/default.yaml
|
|
11
|
-
#
|
|
12
|
-
# Keep this file thin. It's read by chief-of-staff for audit reports and
|
|
13
|
-
# by any agent that needs project-wide signals.
|
|
14
|
-
|
|
15
|
-
# Display name shown in reports and Slack messages.
|
|
16
|
-
display_name: Acme Corp
|
|
17
|
-
|
|
18
|
-
# Stage: idea | pre-launch | early | growth | mature
|
|
19
|
-
stage: early
|
|
20
|
-
|
|
21
|
-
# Primary go-to-market motion. Drives default agent suggestions.
|
|
22
|
-
# Options: outbound | inbound | plg | hybrid
|
|
23
|
-
motion: outbound
|
|
24
|
-
|
|
25
|
-
# Default approval channel for HITL — used when an agent's instance config
|
|
26
|
-
# leaves approval_channel unset.
|
|
27
|
-
# Options: slack | inline | auto
|
|
28
|
-
approval_channel: auto
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
last_session: 2026-05-03
|
|
3
|
-
focus: (none — demo project)
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Acme Corp — Session State
|
|
7
|
-
|
|
8
|
-
This file tracks short-term context across Claude Code sessions for this project. Updated via `/save-state` or by the user explicitly. Five lines max.
|
|
9
|
-
|
|
10
|
-
- Status: demo / illustrative
|
|
11
|
-
- Next task: replace with your real project, or delete `_demo/` entirely
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# archive-project.sh — moves a project and all its agent instances to _archive/
|
|
3
|
-
# Usage: bash scripts/archive-project.sh <project> [reason]
|
|
4
|
-
|
|
5
|
-
set -euo pipefail
|
|
6
|
-
|
|
7
|
-
if [ $# -lt 1 ]; then
|
|
8
|
-
echo "Usage: $0 <project> [reason]"
|
|
9
|
-
exit 1
|
|
10
|
-
fi
|
|
11
|
-
|
|
12
|
-
PROJECT="$1"
|
|
13
|
-
REASON="${2:-}"
|
|
14
|
-
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
15
|
-
PROJECT_DIR="$ROOT/projects/$PROJECT"
|
|
16
|
-
|
|
17
|
-
if [ ! -d "$PROJECT_DIR" ]; then
|
|
18
|
-
echo "ERROR: Project '$PROJECT' not found at $PROJECT_DIR"
|
|
19
|
-
exit 1
|
|
20
|
-
fi
|
|
21
|
-
|
|
22
|
-
DATE=$(date +%Y-%m-%d)
|
|
23
|
-
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
24
|
-
|
|
25
|
-
# Find all agent instances for this project
|
|
26
|
-
INSTANCES=()
|
|
27
|
-
while IFS= read -r path; do
|
|
28
|
-
INSTANCES+=("$path")
|
|
29
|
-
done < <(find "$ROOT" -type d -path "*/projects/$PROJECT" -not -path "*/_template/*" -not -path "*/_archive/*" 2>/dev/null | grep -v "^$ROOT/projects/$PROJECT$" || true)
|
|
30
|
-
|
|
31
|
-
# Determine archive suffix (handle same-day re-archiving)
|
|
32
|
-
SUFFIX="$DATE"
|
|
33
|
-
COUNTER=2
|
|
34
|
-
while [ -d "$ROOT/_archive/projects/$PROJECT-$SUFFIX" ]; do
|
|
35
|
-
SUFFIX="$DATE-$COUNTER"
|
|
36
|
-
COUNTER=$((COUNTER + 1))
|
|
37
|
-
done
|
|
38
|
-
|
|
39
|
-
echo "Archiving project: $PROJECT (suffix: $SUFFIX)"
|
|
40
|
-
|
|
41
|
-
# Create archive root
|
|
42
|
-
mkdir -p "$ROOT/_archive/projects"
|
|
43
|
-
|
|
44
|
-
# Move project root
|
|
45
|
-
mv "$PROJECT_DIR" "$ROOT/_archive/projects/$PROJECT-$SUFFIX"
|
|
46
|
-
echo " Moved: projects/$PROJECT/ → _archive/projects/$PROJECT-$SUFFIX/"
|
|
47
|
-
|
|
48
|
-
# Move each instance
|
|
49
|
-
for inst in "${INSTANCES[@]}"; do
|
|
50
|
-
REL="${inst#$ROOT/}"
|
|
51
|
-
PARENT_DIR=$(dirname "$REL")
|
|
52
|
-
ARCHIVE_PARENT="$ROOT/_archive/$PARENT_DIR"
|
|
53
|
-
mkdir -p "$ARCHIVE_PARENT"
|
|
54
|
-
mv "$inst" "$ARCHIVE_PARENT/$PROJECT-$SUFFIX"
|
|
55
|
-
echo " Moved: $REL/ → _archive/$PARENT_DIR/$PROJECT-$SUFFIX/"
|
|
56
|
-
done
|
|
57
|
-
|
|
58
|
-
# Write ARCHIVED.md
|
|
59
|
-
cat > "$ROOT/_archive/projects/$PROJECT-$SUFFIX/ARCHIVED.md" << EOF
|
|
60
|
-
---
|
|
61
|
-
archived_at: $TIMESTAMP
|
|
62
|
-
project: $PROJECT
|
|
63
|
-
archive_suffix: $SUFFIX
|
|
64
|
-
reason: ${REASON:-(not specified)}
|
|
65
|
-
---
|
|
66
|
-
|
|
67
|
-
# Archived: $PROJECT
|
|
68
|
-
|
|
69
|
-
## Paths archived
|
|
70
|
-
- _archive/projects/$PROJECT-$SUFFIX/ (project root)
|
|
71
|
-
$(for inst in "${INSTANCES[@]}"; do
|
|
72
|
-
REL="${inst#$ROOT/}"
|
|
73
|
-
PARENT_DIR=$(dirname "$REL")
|
|
74
|
-
echo "- _archive/$PARENT_DIR/$PROJECT-$SUFFIX/ (instance)"
|
|
75
|
-
done)
|
|
76
|
-
|
|
77
|
-
## To restore
|
|
78
|
-
\`\`\`bash
|
|
79
|
-
bash scripts/unarchive-project.sh $PROJECT $SUFFIX
|
|
80
|
-
\`\`\`
|
|
81
|
-
EOF
|
|
82
|
-
|
|
83
|
-
# Operation log
|
|
84
|
-
LOG_DIR="$ROOT/chief-of-staff/logs/$(date +%Y-%m)"
|
|
85
|
-
mkdir -p "$LOG_DIR"
|
|
86
|
-
LOG_FILE="$LOG_DIR/operations-$(date +%Y-%m-%d).md"
|
|
87
|
-
{
|
|
88
|
-
echo ""
|
|
89
|
-
echo "## $TIMESTAMP — archive-project: $PROJECT"
|
|
90
|
-
echo "Suffix: $SUFFIX"
|
|
91
|
-
echo "Instances archived: ${#INSTANCES[@]}"
|
|
92
|
-
[ -n "$REASON" ] && echo "Reason: $REASON"
|
|
93
|
-
} >> "$LOG_FILE"
|
|
94
|
-
|
|
95
|
-
echo ""
|
|
96
|
-
echo "✓ Archive complete."
|
|
97
|
-
echo " ARCHIVED.md: $ROOT/_archive/projects/$PROJECT-$SUFFIX/ARCHIVED.md"
|
|
98
|
-
echo " Operation log: $LOG_FILE"
|