| name | draft-publish-team |
| description | Publishes the curator's local context to the shared GitHub repo. Reads change log entries since last publish, builds CHANGES.jsonl, pushes to the team repo via the separate-clone pattern. Run whenever you want teammates to see updated context.
|
/draft:publish-team — Publish Context to Shared Repo
Push your local product context to the shared team repo so teammates can load it.
Flags: --no-confirm — skip the preview step (used by /draft:setup-collab auto-seed and automation).
Step 1: Read config and verify auth
Read $DRAFT_WORKSPACE/config/collaboration.json using json.loads().
Read $DRAFT_WORKSPACE/config/local.json using json.loads().
If config/collaboration.json is missing or mode is not github:
Error: Collaboration not configured. Run /draft:setup-collab first.
Hard stop.
Verify gh auth:
gh auth status
If fails:
GitHub auth expired. Run `gh auth login --web` then re-run /publish-team.
Hard stop.
Step 1.5: Apply pending synthesis proposals from proposals/
Check for .md files in $DRAFT_WORKSPACE/proposals/.
If proposals/ is empty or doesn't exist: skip to Step 2.
If proposals/ has files:
-
List the files:
ls "$DRAFT_WORKSPACE/proposals/"*.md 2>/dev/null
-
For each .md file, read and display it to the user:
Pending synthesis proposals:
─────────────────────────────────────────────────────
File: 20260517T024408Z-853ea41f.md
Session: 853ea41f | Source: session | Synthesized by: claude-code
[markdown body content — the human-readable preview section]
─────────────────────────────────────────────────────
-
Ask the user: "Apply all synthesis proposals to context before publishing? [Y/n/skip-all]"
Y or Enter → apply all
n → show each proposal individually and ask per-file (y/skip/delete)
skip-all → skip proposals/ entirely for this publish (files stay for next time)
delete-all → archive all proposals to proposals/rejected/ without applying
-
Applying a proposal: Parse the YAML frontmatter context_updates and apply each update:
-
After applying: note the session_id, synthesized_by, and input_source from each file's
frontmatter — you will need these for Step 4 CHANGES.jsonl entries.
-
After successful push (Step 4): archive applied proposals/ files to accepted/:
mkdir -p "$DRAFT_WORKSPACE/proposals/accepted" "$DRAFT_WORKSPACE/proposals/rejected"
mv "$DRAFT_WORKSPACE/proposals/<applied_file>.md" "$DRAFT_WORKSPACE/proposals/accepted/<applied_file>.md"
Only archive files that were successfully applied AND pushed.
For delete-all: archive all pending files to rejected/ instead:
mv "$DRAFT_WORKSPACE/proposals/"*.md "$DRAFT_WORKSPACE/proposals/rejected/"
Step 2: Collect changes
Read all files in $DRAFT_WORKSPACE/context/*/log/ with modification timestamps newer than config/local.json:last_published.
- If
last_published is null (from local.json): this is the first manual publish — read ALL log entries.
- If no log/ directories exist or they are empty: no log-based entries.
Case: last_published is null AND no log entries exist
First publish with no history. Generate synthetic CHANGES entries — one per context dimension where index.md description is not "No information recorded yet":
For each qualifying dimension, compute the ID deterministically via bash:
ts=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
gh_username=$(gh api user --jq .login)
dimension="[company|product|team|priorities|decisions|tensions]"
file="context/${dimension}/index.md"
id=$(echo -n "${ts}${gh_username}${dimension}${file}" | sha256sum | cut -c1-8)
Generate CHANGES entry:
{"id":"[computed]","ts":"[current ISO 8601]","author":"[gh_username]","dimension":"[dim]","summary":"Initial context snapshot","file":"context/[dim]/index.md","log_entry":null}
Case: no entries found since last_published
Print: "Nothing new to publish since [last_published]."
Exit 0.
IMPORTANT: Never compute IDs mentally. Always run the sha256 bash command above.
Step 3: Preview (skip if --no-confirm)
Show:
Publishing to: [team_repo_url] / [team_repo_subdir]
Changes:
[N] entries across [dimensions list]
[list of summaries, truncated at 80 chars each]
Teammates: [list from collaboration.json]
Confirm? [Y/n]
If n or N: "Aborted. Nothing published." Exit 0.
Step 4: Execute — separate-clone pattern
The Draft workspace (~/.draft/workspace) is NEVER initialized as a git repo.
All git operations run in a short-lived temp directory.
TMPDIR=$(mktemp -d /tmp/draft-publish-XXXX)
git clone [team_repo_url] "$TMPDIR"
Set the subdir prefix. If team_repo_subdir is root, use no prefix (write to repo root):
Create target directories:
mkdir -p "$SUBDIR_PATH/context"
mkdir -p "$SUBDIR_PATH/config"
Copy context from workspace:
cp -r "$DRAFT_WORKSPACE/context/" "$SUBDIR_PATH/context/"
personal/ is structurally excluded — it lives outside context/ and is never under the copy source path.
Copy collaboration config:
cp "$DRAFT_WORKSPACE/config/collaboration.json" "$SUBDIR_PATH/config/collaboration.json"
Build CHANGES.jsonl:
-
Read existing $SUBDIR_PATH/CHANGES.jsonl if it exists (preserves history).
-
For each new CHANGES entry, compute ID via bash:
id=$(echo -n "${ts}${author}${dimension}${file}" | sha256sum | cut -c1-8)
-
Append new entries (one JSON object per line). Two entry types:
Manual publish (from log/ entries):
{"id":"[computed]","ts":"[ISO8601]","type":"manual-publish","author":"[gh_username]","dimension":"[dim]","summary":"...","file":"context/[dim]/index.md","log_entry":"..."}
Daemon synthesis (from proposals/ proposals applied in Step 1.5):
For each applied synthesis file, compute ID the same way (sha256 of ts+author+source+session_id):
id=$(echo -n "${ts}${gh_username}${input_source}${session_id}" | sha256sum | cut -c1-8)
{"id":"[computed]","ts":"[ISO8601]","type":"daemon-synthesis","source":"[input_source]","session_id":"[session_id]","synthesized_by":"[synthesized_by]","approved_by":"[gh_username]","files":["context/product/index.md",...]}
-
Write back to $SUBDIR_PATH/CHANGES.jsonl.
Generate semantic commit message. If synthesis proposals were applied, note them:
"[N] context updates: [dimension list]" # manual only
"[N] context updates + [M] synthesis proposals applied" # with synthesis
Stage and commit:
git -C "$TMPDIR" add "[subdir_relative]/context/" "[subdir_relative]/config/" "[subdir_relative]/CHANGES.jsonl"
git -C "$TMPDIR" commit -m "[semantic message]"
git -C "$TMPDIR" push
If push fails:
rm -rf "$TMPDIR"
Print the error. DO NOT update config/local.json.
Publish failed. Check your network and repo access, then try again. Nothing was changed locally.
Exit 1.
rm -rf "$TMPDIR"
Step 5: Update local state (success only)
Update $DRAFT_WORKSPACE/config/local.json:
- Read the file with
json.loads(), set last_published to the current ISO 8601 timestamp, write back with json.dumps().
Print:
Published [N] changes to [team_repo_url]