| name | ds-update-agentic-engineering |
| description | Handles the full edit-sync-build-commit-push cycle for methodology and tooling files under your agentic-engineering install (resolved at runtime from `~/.agentic/agentic-engineering-config.json` `repo |
| user-invocable | true |
/ds-update-agentic-engineering
Run the Activation preflight from METHODOLOGY.md before proceeding. If inactive, no-op and exit.
Handles the full edit-sync-build-commit-push cycle for methodology and tooling files under your agentic-engineering install (resolved at runtime from ~/.agentic/agentic-engineering-config.json repo_dir, default ~/DinoStack).
In-repo only. This command edits files inside the agentic-engineering/DinoStack repo and spawns Workers that run in isolation worktrees. Isolation worktrees are created from the current session's git repo, not from AE_REPO_DIR - so running this from a different project corrupts both repos' worktree state and cleanup. Step 0a enforces that the session is rooted in the AE repo; otherwise it writes a handoff doc and stops without editing.
When to use - use whenever ANY of these hold:
- (a) The user asks to edit, add, or remove a rule, convention, agent definition, command, reference, or protocol doc under your agentic-engineering install.
- (b) The user says "update the methodology", "change the protocol", "edit the wrap skill", "add an agent", "rename a command", or anything similar that implies changing a file in the agentic-engineering repo.
- (c) You are about to use Edit or Write on any file whose absolute path is within one of the in-scope directories listed in Scope below (e.g.
<AE_REPO_DIR>/content/**, <AE_REPO_DIR>/.codex/skill/**, the build scripts, <AE_REPO_DIR>/hooks/**, or <AE_REPO_DIR>/.codex/hooks/**). Files outside those directories (docs, README, build artifacts, top-level config) may be edited directly.
Why it matters: Without this command's Step 0 git sync, concurrent edits from multiple machines produce push conflicts and messy rebases; without Step 4 commit+push, edits pile up uncommitted locally.
Do NOT bypass: The main agent must NOT edit files in the in-scope directories listed in Scope with direct Edit/Write calls. The only exception is the permission-blocked path documented below: if a spawned Worker has returned a BLOCKED status citing Edit permission denial by the permission system, the main session may apply the edit directly per the permission-blocked path in this command. That is the sole carve-out. If you find yourself about to Edit or Write a file in one of the in-scope directories without that specific trigger, stop and invoke /ds-update-agentic-engineering instead. Files outside the in-scope list (docs, README, build artifacts, top-level config) may be edited directly and are governed by the normal Trivial/Elevated risk tiers.
Scope:
In scope (must route through /ds-update-agentic-engineering):
content/** - the single source of truth for all rules, commands, references, and agent definitions
.codex/skill/** - the Codex adapter source
.claude/build.sh, .codex/build.sh, .cursor/build.sh - build scripts that generate the adapter artifacts
hooks/** and .codex/hooks/** - git hooks (pre-commit, etc.) and Codex session hooks (risk-reminder, stop-context)
Out of scope (direct Edit/Write is fine; normal Trivial/Elevated tiers apply):
docs/** - the docs site (including docs/index.html, docs/slides/**, etc.)
README.md, CONTRIBUTING.md, LICENSE, top-level config files (vercel.json, .gitignore, etc.)
- Build artifacts regenerated by the build scripts:
.claude/commands/**, .claude/agents/**, .codex/commands/**, .codex/agents/**, .codex/AGENTS.md, .codex/README.md, .cursor/commands/**, .cursor/rules/**, .cursor/README.md
.vercel/, .agentic/compression-state.json, and other machine-local state files
Note: .claude/skills/agentic-engineering/** files are symlinks into content/ - editing them is functionally editing content/, so they remain IN scope via the content/** rule above. This is a clarification, not a separate scope.
Step 0a - Directory gate (run before Step 0)
This is the first action of the command, before any git sync or edit. It guarantees the session repo IS the AE repo so that Worker isolation worktrees are created in the correct repo.
Resolve AE_REPO_DIR once at the start of the command - it persists for all subsequent steps in this invocation:
AE_REPO_DIR=""
AE_CONFIG="$HOME/.agentic/agentic-engineering-config.json"
if [[ -f "$AE_CONFIG" ]]; then
AE_REPO_DIR="$(python3 -c "
import json, sys
try:
with open(sys.argv[1]) as f:
print(json.load(f).get('repo_dir', ''))
except Exception:
print('')
" "$AE_CONFIG" 2>/dev/null)"
fi
if [[ -z "$AE_REPO_DIR" ]] || ! git -C "$AE_REPO_DIR" rev-parse --git-dir >/dev/null 2>&1; then
AE_REPO_DIR="$HOME/DinoStack"
fi
Fallback behavior: if ~/.agentic/agentic-engineering-config.json does not exist, has no repo_dir key, or repo_dir is not a git repository, AE_REPO_DIR defaults to ~/DinoStack exactly as before.
Canonical resolver: the inline block above is the reference implementation. The same logic is extracted into scripts/lib/repo-dir.sh (resolve_repo_dir function), which is what hooks and the installer use at runtime. If you need to understand or audit the resolution behavior, scripts/lib/repo-dir.sh is the single source to read - the command spec above and the shell lib must stay in sync.
Compare the session repo against AE_REPO_DIR by canonical path:
SESSION_REPO="$(git rev-parse --show-toplevel 2>/dev/null || true)"
AE_REAL="$(cd "$AE_REPO_DIR" 2>/dev/null && pwd -P || true)"
SESSION_REAL="$(cd "$SESSION_REPO" 2>/dev/null && pwd -P || true)"
Decision:
- In-repo (
SESSION_REAL is non-empty AND equals AE_REAL): proceed to Step 0. Worker isolation worktrees will be created in the AE repo, which is correct.
- Cross-directory (no git repo, or
SESSION_REAL does not equal AE_REAL): the gate triggers. Do NOT spawn any Worker, do NOT edit any file, do NOT cd into AE_REPO_DIR to edit it. Instead:
- Capture the intended change from the user's request: a one-line title, the rationale, the target file(s) under
content/, and any decisions already made in this session.
- Choose the handoff destination:
- If
AE_REAL is non-empty (the AE repo exists): write to $AE_REPO_DIR/docs/planning/handoff-<YYYYMMDD-HHMMSS>-<slug>.md. Create docs/planning/ with mkdir -p if absent; it is local and gitignored per convention, so it never lands in a commit.
- If
AE_REAL is empty (AE_REPO_DIR is unreachable or not a git repo - a broken install): do NOT create a phantom directory there. Write the handoff to $HOME/.agentic/handoff-<YYYYMMDD-HHMMSS>-<slug>.md instead (mkdir -p "$HOME/.agentic"), and include the warning line from step 3 in the redirect message.
Derive <slug> from the change title (lowercase, hyphenated); derive the timestamp from date -u +%Y%m%d-%H%M%S.
- When
AE_REAL is empty, also include the broken-install warning line shown below. Print the redirect message below and STOP. Do not continue to Step 0.
Note: a git worktree derived from the AE repo (e.g. a path under AE_REPO_DIR/.agentic/worktrees/) resolves to its own toplevel, not AE_REAL, so it also trips this gate. That is intended: /ds-update-agentic-engineering runs from the main checkout at AE_REPO_DIR, never from a worktree derived from it.
Handoff doc template:
# Methodology change handoff
- Created: <ISO8601 from `date -u +%Y-%m-%dT%H:%M:%SZ`>
- From session in: <SESSION_REAL, or "(no git repo)" if empty>
- Target repo: <AE_REPO_DIR>
## Intended change
<one-line title>
## Rationale
<why this change>
## Target files
- content/...
## Decisions already made
- <bullets, or "none yet">
## Next step
Open a Claude Code session rooted in <AE_REPO_DIR> and run `/ds-update-agentic-engineering`, referencing this handoff.
Redirect message template (print verbatim, substituting the resolved paths). When AE_REAL is empty, also include the broken-install warning line shown below (omit it when AE_REAL is non-empty):
/ds-update-agentic-engineering was invoked from outside the AE repo.
Session repo: <SESSION_REAL, or "(no git repo)">
AE repo: <AE_REPO_DIR>
(Warning: AE repo path does not exist or is not a git repo - check your installation.)
Editing the methodology from here would create isolation worktrees in the wrong repo, so I have NOT made any edits.
Handoff written to: <handoff path>
Next: open a new Claude Code session rooted in <AE_REPO_DIR> and run /ds-update-agentic-engineering (reference the handoff above).
Step 0 - Pre-flight git sync
Before making any edits, the main agent (not a subagent - git state decisions require main-agent judgment) resolves the repo location and runs the following checks.
AE_REPO_DIR is already resolved in Step 0a and persists for this invocation.
cd "$AE_REPO_DIR" && git fetch origin
- Run
git status --porcelain to check for uncommitted changes.
- Run
git rev-list --left-right --count HEAD...origin/main to measure divergence.
Decision matrix:
- Clean tree AND local == origin/main: proceed to Step 1.
- Clean tree AND origin is ahead (local behind): capture
OLD_HEAD="$(git -C "$AE_REPO_DIR" rev-parse HEAD)", fast-forward pull (git pull --ff-only origin main), capture NEW_HEAD="$(git -C "$AE_REPO_DIR" rev-parse HEAD)", then run the hook-change note check below, then proceed to Step 1.
- Clean tree AND local is ahead (origin behind): note this in the user-facing summary but proceed - the push in Step 4 will include the prior commits too.
- Clean tree AND both are ahead (divergence): STOP. Tell the user: "Local and origin have diverged (N local commits, M origin commits). Resolve the divergence manually before running /ds-update-agentic-engineering again." Do not attempt auto-merge or rebase.
- Dirty tree (any uncommitted changes): STOP. Show the user
git status output and tell them to commit, stash, or discard before running /ds-update-agentic-engineering. Do not auto-stash - the WIP may be important and this command is not authorized to touch it.
Hook-change note (after any pull in this step):
HOOK_CHANGES="$(git -C "$AE_REPO_DIR" diff --name-only "$OLD_HEAD" "$NEW_HEAD" -- hooks/)"
If HOOK_CHANGES is non-empty, print the following informational note (substituting HOOK_CHANGES as a comma-joined list into Changed:), then continue. Never stop the flow for this - it is informational only, not an actionable warning. Step 4.5 below auto-refreshes this machine's local hook snapshot once this command's own edit is pushed, independent of the pull handled here.
note: this update changed files under hooks/. A bare git pull no longer changes a running session's hooks (they load from a session-stable snapshot, not the checkout) - but this flow also runs the install step, which refreshes this checkout's SHARED hook snapshot in place. So any OTHER Claude Code session already open against this checkout will pick up the changed hooks on its next tool call. If that matters, have those sessions /exit and restart once this update finishes. Changed: <comma-joined HOOK_CHANGES>
If HOOK_CHANGES is empty, skip silently.
Step 1 - Spawn a Worker
Spawn a Worker subagent with instructions:
- Read the current file(s) to be changed.
- Apply the edit using the Edit tool.
- If editing
content/rules/, content/references/, or content/agents/: edit only the content/ path. The corresponding .claude/skills/agentic-engineering/ and .claude/agents/ paths are symlinks pointing into content/ - but because the Worker runs in an isolation worktree, the edit lives in the worktree branch and is NOT live in the conductor's checkout until Step 2.5 cherry-picks it in. (On the permission-blocked in-place path where the conductor edits directly, the symlinks do make the change live immediately - but that is the exception, not the rule.) The other ten adapters are built artifacts, so the Step 3 build is still required before commit - the adapter-sync CI gate fails otherwise.
- If editing
content/commands/: edit only the content/commands/ path. The .claude/commands/*.md copies are build artifacts - build.sh prepends the /agentic-engineering prerequisite blockquote and writes the result to .claude/commands/. The build must be run after approval for the change to take effect.
- Commit the edit to the isolation worktree branch with
git commit -s and a short message describing the change.
- Return the full diff, the commit SHA (full 40-character), and the worktree branch name.
- If the Edit cannot be applied for any reason other than a Claude Code permission denial (file not found, ambiguous anchor, etc.), return a clear error description instead of a diff - do not attempt workarounds.
Permission-blocked path
If the Worker in Step 1 returns a BLOCKED status explicitly citing an Edit permission denial by the Claude Code permission system (exact form observed in practice: "BLOCKED - Edit permission was denied by the permission system"), the main session may apply the edit directly, then present the diff to the user in Step 2 as normal. The user approval gate in Step 2 is preserved without exception - the main session never applies an edit and proceeds without human review. Step 3 proceeds only after approval.
Step 1.5 - Vision-alignment check
Every invocation of this command edits methodology-core files by definition (see Scope above) -
this check runs unconditionally, with no separate proportionality gate.
Before presenting the diff in Step 2, read docs/overview/vision.md if it exists (it is the
operator-owned North Star for this repo) and apply its "How to use this for PR alignment" rubric
to the diff produced in Step 1: does the change advance at least one pillar (guard operator
attention, produce verifiable outcomes autonomously, low friction, works for everyone) without
regressing another?
Write a short alignment note (2-4 sentences - this is a check, not a report):
- Which pillar(s) the change advances, in one line each.
- Any pillar it plausibly regresses or trades off, named plainly - do not omit a real trade-off
to make the note look cleaner.
- If
docs/overview/vision.md does not exist, state that plainly and skip the rest of this step.
This is a surface, not a gate: a misalignment you notice does not stop the flow. State it in
the note and let the human approval in Step 2 be the decision point - per vision.md's own rubric,
misalignment is "a direction signal for the operator... not necessarily a request-changes
verdict." Do not skip this step because the diff looks small; a one-line rule change can still
shift the methodology's direction.
Carry the alignment note into Step 2.
Step 2 - Present to the user
Show the diff, state what the change does, and include the vision-alignment note from Step 1.5. Remind the user that the per-adapter copies are build artifacts that Step 3 regenerates. Wait for explicit approval.
Step 2.5 - Integrate the Worker's commit
Skip this step on the permission-blocked in-place path. On that path the conductor already edited the checkout directly (no isolation worktree), so there is nothing to cherry-pick - proceed straight to Step 3.
Otherwise (normal isolation-worktree path), after the user approves in Step 2:
-
Make sure the conductor's main checkout is current. Run from $AE_REPO_DIR:
cd "$AE_REPO_DIR" && git fetch origin
-
Check whether local main has diverged from origin/main using the same decision matrix as Step 0:
- Local behind, fast-forwardable: capture
OLD_HEAD="$(git -C "$AE_REPO_DIR" rev-parse HEAD)", git pull --ff-only origin main, capture NEW_HEAD="$(git -C "$AE_REPO_DIR" rev-parse HEAD)", run the same hook-change note check as Step 0 (git -C "$AE_REPO_DIR" diff --name-only "$OLD_HEAD" "$NEW_HEAD" -- hooks/; print the shared note when non-empty, never block), then continue.
- Diverged (both sides ahead): STOP. Tell the user: "Local and origin have diverged since Step 0. Resolve the divergence manually before continuing." Do not force or auto-merge.
- Local ahead or equal: proceed.
This closes the window where the Worker's worktree was based on a now-stale main tip - the cherry-pick lands on the current HEAD after this sync.
-
Cherry-pick the Worker's commit into the conductor's checkout - use the full 40-character SHA returned in Step 1, NOT the worktree branch name:
git cherry-pick --no-commit <worker-sha>
Do NOT use git merge <worktree-branch>. The worktree branch is based on the main tip at Worker spawn time. If main has advanced since then, merging the branch can resurrect files that were deleted on the current main - the "worktrees do not replay deletions on re-base" hazard. Cherry-pick applies only the delta the Worker introduced, which is safe regardless of base drift.
-
Verify the cherry-pick applied cleanly - two checks in order:
-
Conflict check (first): Run git ls-files -u and inspect git status --porcelain. If git ls-files -u produces any output, or the status shows any line with a leading UU, AA, or other unmerged-path state code, or .git/CHERRY_PICK_HEAD still exists, the cherry-pick conflicted. Run git cherry-pick --abort immediately and STOP - report the conflicting path(s) to the user. This is the same-file base-drift collision that a concurrent PR to the same content/ path produces during the Worker run. Do NOT proceed to Step 3.
-
Scope check (second): If no conflicts, run git status --porcelain and verify the working tree shows ONLY the intended content/ source path(s). If any other file appears as modified or added, STOP and show the user - a wider delta means the worktree base drifted further than expected or the Worker touched something outside its scope.
Step 3 - Run the build
After approval, if the diff touches ANY file under content/, rebuild every adapter so the committed adapter artifacts stay in sync. The adapter-sync CI gate rebuilds all of them and fails on any drift, so a partial build - or skipping the build for a rules/references/agents edit - makes the push fail. Run from $AE_REPO_DIR:
cd "$AE_REPO_DIR" && \
bash .claude/build.sh && bash .cursor/build.sh && bash .codex/build.sh && \
bash .gemini/build.sh && bash .kimi/build.sh && bash .opencode/build.sh && \
bash .omp/build.sh && bash .pi/build.sh && bash .hermes/build.sh && bash .openclaw/build.sh && \
bash .copilot/build.sh
Then run git status --porcelain and confirm the only changes are the content/ source file(s) plus their regenerated adapter copies. If any unrelated source file shows as modified, STOP and show the user - a build script can silently revert an out-of-date source file (the adapter-rebuild revert hazard).
If the diff touches content/sections/, also regenerate the methodology baseline in the same commit: scripts/.methodology-baseline.sha256 must be updated to match the rebuilt methodology body (see scripts/check-methodology-drift.sh). This is a separate CI gate from adapter-sync. Regenerate it with:
bash scripts/build-methodology.sh | shasum -a 256 | awk '{print $1}' > scripts/.methodology-baseline.sha256
Note: .claude/skills/agentic-engineering/ and .claude/agents/ are symlinks into content/, so content/rules/, content/references/, and content/agents/ edits are immediately live in your own Claude session with no build. The build above is still required so the other ten adapters' committed artifacts match content/.
Step 3.5 - Docs update check
After the build, evaluate whether the content change affects concepts covered in docs/index.html or docs/slides/. This step runs before the commit so any doc updates land in the same commit.
Significant changes (require action): new or removed protocol behavior, changed table values (e.g. tier table, risk table), added/removed/renamed rules, agents, or commands, or anything a reader of the published docs would now encounter as incorrect.
Minor changes (skip silently): phrasing adjustments with no behavioral or structural effect.
If the change is significant:
- Check which docs reference the affected concept. The main reference is
docs/index.html; slides live in docs/slides/. Use grep to locate the relevant sections quickly.
- For simple value changes (a table cell, a model name, a step number): apply the update directly to the doc file(s) and include them in the commit.
- For structural changes (new rule, new agent, new command, removed section): surface a specific note to the user - name the exact doc file(s) and section(s) that are now stale, and what needs updating. Do not just say "consider updating docs". Then wait for the user to decide whether to update now or track it separately before proceeding to Step 4.
- If any
docs/slides/*-slides.md deck content changed as part of this update, run bash scripts/build-slides.sh and stage the regenerated docs/slides/*.html into the same commit. Never hand-edit the .html - it is build output enforced by the slides-sync CI gate. Upgrading marp is an intentional same-PR action: bump scripts/package.json, regenerate scripts/package-lock.json, and rebuild all decks in the same commit.
Step 4 - Commit and push
Only runs if Steps 1-3 actually made changes.
- Run
git status --porcelain to list what changed. Expect exactly: the content/ source path(s) applied by the Step 2.5 cherry-pick (or, on the permission-blocked in-place path, edited directly by the conductor) plus the adapter artifacts regenerated by Step 3. There is no separate "files edited in Step 1" set in the conductor checkout - the Worker's edit reaches this checkout only via the Step 2.5 cherry-pick.
- Verify the staged/unstaged file list matches what was intended. If unfamiliar files appear (WIP that somehow materialized), STOP and show the user.
- Stage the edited files by explicit path - never
git add -A or git add .. Explicitly name each file path on the git add command line. This includes both the content/ source file and all adapter artifacts regenerated by Step 3.
- Capture
PRE_PUSH_HEAD="$(git -C "$AE_REPO_DIR" rev-parse HEAD)" - the pre-commit HEAD, before the commit below is created. Step 4.5 diffs from this point to detect whether the commit this step is about to push touches hook paths.
- Commit with
git commit -s and a message summarizing what rule/command changed. Format: docs(protocol): <short summary> or the natural commit type for the file being edited. No Claude footer. No em dashes. The -s adds a Signed-off-by: trailer from the repo's configured git identity (which must match the commit author email); the agentic-engineering repo enforces a DCO Signed-off-by check, so the -s is mandatory here or CI fails.
- Push with
git push origin main.
- If push is rejected because origin is ahead (race condition - someone pushed between the Step 2.5 sync and the Step 4 push): run
git pull --rebase origin main. If the rebase is clean, retry the push. If the rebase has conflicts, STOP and escalate to the user with git status output showing the conflict files. Do NOT force-push, do NOT git rebase --abort, do NOT git reset. The user resolves the conflict manually.
- Report the final commit SHA and push result to the user.
Step 4.5 - Refresh local hook snapshot
Only runs if Step 4 actually pushed a commit. Best-effort and non-blocking - a failed refresh warns but does not fail the flow.
Why this step exists: Step 3 runs build.sh, never install.sh. hooks/** and .codex/hooks/** are in scope for this command (see Scope above), so a maintainer who edits a hook file and runs /ds-update-agentic-engineering would otherwise push the change but keep running their own pre-edit local hook snapshot on this machine - the dogfooding gap. This step closes it automatically.
4.5a - Detect whether the pushed commit touched hook paths, using the commit range from Step 4 (PRE_PUSH_HEAD captured before the commit, to the current HEAD after the push - and after any Step 4 item 7 rebase - succeeded):
POST_PUSH_HEAD="$(git -C "$AE_REPO_DIR" rev-parse HEAD)"
HOOK_PATHS_CHANGED="$(git -C "$AE_REPO_DIR" diff --name-only "$PRE_PUSH_HEAD" "$POST_PUSH_HEAD" -- hooks/ .codex/hooks/ .codex/config/hooks.json .gemini/hooks/ .kimi/hooks/)"
If HOOK_PATHS_CHANGED is empty, skip the rest of this step silently.
4.5b - Auto-run the refresh (no separate confirmation): Step 2's user approval already covered this diff, including any hook-path edits within it, and install.sh is idempotent and scoped to this machine's adapter config directories (~/.claude, etc.) - re-running it is not a novel side effect requiring its own gate.
Refresh .claude (always, locked) plus every other adapter marked true in ~/.agentic/agentic-engineering-config.json's adapters map. If that config file or its adapters map is absent or unreadable, fall back to .claude only:
AE_CONFIG="$HOME/.agentic/agentic-engineering-config.json"
REFRESH_ADAPTERS="$(python3 -c "
import json, sys
try:
with open(sys.argv[1]) as f:
cfg = json.load(f)
adapters = sorted(k for k, v in cfg.get('adapters', {}).items() if v)
except Exception:
adapters = []
if '.claude' not in adapters:
adapters.append('.claude')
print(' '.join(adapters))
" "$AE_CONFIG" 2>/dev/null || echo ".claude")"
for adapter in $REFRESH_ADAPTERS; do
if [[ -x "$AE_REPO_DIR/$adapter/install.sh" ]]; then
bash "$AE_REPO_DIR/$adapter/install.sh" || echo "warning: $adapter/install.sh refresh failed - this machine's $adapter hook snapshot may still be stale. Re-run manually: bash $AE_REPO_DIR/$adapter/install.sh"
fi
done
4.5c - Report: include the refreshed adapter(s) and their snapshot path(s) in the final summary shown to the user alongside the Step 4 commit SHA and push result. On a refresh failure, surface the warning line verbatim rather than silently swallowing it.
Note: This command governs edits to its own source file - the recursion is intentional. Use /ds-update-agentic-engineering when modifying this file. Because of Step 0a, that editing session must itself be rooted in the AE repo - if you are elsewhere, the gate produces a handoff and you continue in a session opened in $AE_REPO_DIR.