You are the writing infrastructure deployer. Deploy the web fiction writing toolset to the user's project directory: adapted CLIs use dedicated hooks/agents/config; environments such as NarraFork, Web AI, and custom Agents use the generic file mode.
Iron rule of execution: do not overwrite the user's existing configuration; merge rather than replace.
Interactive tool compatibility gate: In this Skill, AskUserQuestion means "the user must be made to choose"; it does not mean a tool with the same name must exist. When the current runtime does not expose this tool (including some TRAE Code, WorkBuddy / CodeBuddy Code, and Web AI sessions), the main Agent must directly ask the same short question in the current main conversation and wait for an answer; it must not skip confirmation because the tool is missing, fabricate a selected result, or have a sub-Agent ask on its behalf.
Phase 1: Detect project status
First self-check the reference directory: Based on the directory where the currently executing SKILL.md resides, list the subdirectories under the references/ at the same level as it, and verify whether all 10 names below are presentand all non-empty——agent-references、templates、opencode、codex、zcode、trae、workbuddy、openclaw、reasonix、generic; the same-level scripts/merge-claude-settings.py、scripts/merge-codex-hooks.py、scripts/merge-trae-hooks.py、scripts/trae-core-ownership.py、scripts/merge-workbuddy-settings.py and scripts/copy-path-safety.py must also exist (Claude/Codex/TRAE/WorkBuddy hooks merging, shared-core ownership verification, and recursive copy safety pre-checks depend on them). If anything is missing, the skill package was not fully installed,stop immediately and do not write any deployment files, distinguish in the report between "missing directory" and "empty directory", and give repair instructions: "The story-setup reference package is incomplete, missing {directory name}. Reinstall oh-story-claudecode according to your installation method (for command-line installs, rerun npx skills add https://github.com/qin1473692580-ux/oh-story-claudecode/releases/latest/download/oh-story-release.zip -y -g, for marketplace / Plugin Management installs, reinstall in the panel), then run /story-setup."
The criterion is "whether there is
SKILL.md": only look at theSKILL.mdat the same level as the currently executingreferences/. In-project.claude/skills/story-setup/、.codex/skills/story-setup/and OpenCode'sskills/story-setup/only havereferences/agent-references/, and do not containSKILL.md, so they will not be the execution directory, and you should not use them for verification either. The project copies for ZCode / TRAE Code / WorkBuddy / CodeBuddy Code / OpenClaw / Reasonix / generic are copies of the entire skill and come withSKILL.md, so the 10 subdirectories are complete by nature; verify them as usual.
- Check whether the current directory has already been deployed (exists
.story-deployed)agents_versionmissing, non-integer, or less than39→ mark as pending update, continue with the current deploymentagents_version: 39→ use AskUserQuestion to confirm whether to redeploy; state in the prompt that redeployment only usesthe current local skill packageto refresh project files; to get a new version of the skill itself, first rerun with the pinned GitHub Release assetnpx skills add https://github.com/qin1473692580-ux/oh-story-claudecode/releases/latest/download/oh-story-release.zip -y -g, then come back and rerunagents_versiongreater than39→ the current story-setup is older than the project deployment; stop to avoid a downgrade overwrite, prompt to update oh-story-claudecode first, and do not write any deployment files- Also read the
target_clifield.For deployed projects, the value in the sentinel takes precedence: When non-empty (comma-separated multi-target combinations are preserved as-is), skip the environment detection and selection in steps 5-14 below, and redeploy directly according to these targets. Only when the field is missing or empty does it fall back to detection. When the user explicitly requests adding or removing target ends, use AskUserQuestion to modify based on the existing values, and write the modified values back to the sentinel.
- Check whether there is a book-title directory (a directory containing the
追踪/subdirectory, or a user-defined structure)- Yes → identify as a long-form project, display current project information
- No → identify as a new project or short-form project
- Check whether
.claude/settings.local.jsonexists- Exists → read the existing configuration, merge later
- Does not exist → create a new file later
- Check whether the
.active-bookfile exists- Exists → display the currently active book
- Does not exist → skip
- Check whether
opencode.jsonor.opencode/exists- Exists → identify as an opencode project,
target_cli = opencode - Does not exist → skip
- Exists → identify as an opencode project,
- Check the Codex section in
.codex/、.codex/config.toml、.codex/agents/、.codex/hooks.json、AGENTS.mdCodex section in- Exists → identify as a Codex project,
target_cli = codex - Does not exist → skip
- Exists → identify as a Codex project,
- Check the ZCode section in
.zcode/、.zcode/config.json、zcode.json、.zcode/skills/、.zcode/commands/、AGENTS.mdZCode section in- Exists → identify as a ZCode project,
target_cli = zcode - Does not exist → skip
- Exists → identify as a ZCode project,
- Check
.trae/、.trae/hooks.json、.trae/skills/、.trae/agents/、.trae/commands/、.trae/rules/, or the TRAE section inAGENTS.md(title line contains网文写作工具集(TRAE Code))- Exists → identify as a TRAE Code project,
target_cli = trae - Does not exist → skip
- Exists → identify as a TRAE Code project,
- Check
.codebuddy/、.codebuddy/settings.json、.codebuddy/skills/、.codebuddy/agents/、.codebuddy/commands/、.codebuddy/rules/, or.codebuddy/CODEBUDDY.md/ rootCODEBUDDY.md/ rootAGENTS.mdthe oh-story WorkBuddy management section in- Exists → identify as a WorkBuddy / CodeBuddy Code project,
target_cli = workbuddy - Does not exist → skip
- Exists → identify as a WorkBuddy / CodeBuddy Code project,
- Check
openclaw.json、.openclaw/, or the OpenClaw section inAGENTS.md(title line contains网文写作工具集(OpenClaw))
- Exists → identify as an OpenClaw project,
target_cli = openclaw - Does not exist → skip
- Check
.reasonix/、reasonix-plugin.json、REASONIX.md, or the Reasonix section inAGENTS.md(title line contains网文写作工具集(Reasonix))
- Exists → identify as a Reasonix project,
target_cli = reasonix - Does not exist → skip
- Check the generic section in
AGENTS.md(title line contains网文写作工具集(通用 Agent / Web AI))
- Exists → identify as a generic Web AI project,
target_cli = generic - Does not exist → skip
Steps 8-12 only recognize each target'smutually exclusivemarkers.
skills/*/SKILL.mdofmetadata.openclawis not used as an OpenClaw signal: canonical Chinese main-package Skills all carry this field, and theskills/deployed by the three skills-only paths OpenClaw / Reasonix / generic look the same, so using it for determination would misidentify the latter two as OpenClaw without exception..agents/skills/For the same reason, it is shared by Codex and Reasonix, and also does not serve as a sole criterion. TRAE only recognizes.trae/or the TRAE-specific title line; WorkBuddy only recognizes.codebuddy/or its CODEBUDDY management section; the real distinguishing point of the three skills-only targets is the title line of their respectiveAGENTS.mdtemplates.
- If
.claude/orCLAUDE.md, OpenCode, Codex, ZCode, TRAE Code, WorkBuddy / CodeBuddy Code, OpenClaw, Reasonix, and generic markers all exist at the same time → use AskUserQuestion to let the user choose the target environment (options: Claude Code / OpenCode / Codex / ZCode / TRAE Code / WorkBuddy / CodeBuddy Code / OpenClaw / Reasonix / Generic Web AI or other Agent / any combination) - If none of the nine types of markers exist (brand-new project) → use AskUserQuestion to let the user choose the target environment
- User selects opencode →
target_cli = opencode, create during deploymentopencode.jsonand.opencode/ - User selects claude-code → handle according to the existing logic
- User selects codex →
target_cli = codex, create during deployment.codex/ - User selects zcode →
target_cli = zcode, create during deployment.zcode/, merge rootAGENTS.md, do not create project custom agents - User selects TRAE Code →
target_cli = trae, create during deployment.trae/and merge rootAGENTS.md、.trae/hooks.json, deploy native Skills / Subagents / Commands / Rules / Hooks - User selects WorkBuddy / CodeBuddy Code →
target_cli = workbuddy, create during deployment.codebuddy/, select a single memory file according to the "WorkBuddy memory merge strategy" and merge.codebuddy/settings.json, deploy native Skills / Agents / Commands / Rules / Hooks - User selects openclaw →
target_cli = openclaw, during deployment copy OpenClaw-compatible skills to the projectskills/ - User selects reasonix →
target_cli = reasonix, during deployment copy skills to the projectskills/, write the Reasonix version ofAGENTS.md, do not create project custom agents/hooks - User selects Generic Web AI / other Agent →
target_cli = generic, deploy genericAGENTS.mdand project-localskills/; do not write platform-specific hooks/agents - User selects multi-platform →
target_cli = claude-code,opencode,codex,zcode,trae,workbuddy,openclaw,reasonix,genericsubset (containing only the platforms selected by the user)
Phase 2: Deploy infrastructure
After using AskUserQuestion to confirm the deployment location, execute in order.
The entire Phase 2 is idempotent: directory copying, file writing, and the merge algorithms in the table below produce consistent results when executed repeatedly. If it fails midway due to environmental reasons (tool unavailable, permission denied, network failure), directly rerun this Phase from the beginning; there is no need to clean up partial artifacts first;create only if absent user state files (see the Owner class in the table below) will not be overwritten a second time.
Step 1: Deployment manifest (mechanically checkable)
Recursive copy safety precheck (before any directory replace/copy): first resolve the Source path to an absolute path inside the "currently executing story-setup skill package", resolve the Target path to an absolute path inside the user project, then use the available python3/python/py to run scripts/copy-path-safety.py <source> <target>. Read its JSON result:
status=safe: Only if the paths do not contain each other may this copy item continue.status=same: The source and target point to the same object via realpath/samefile; record this item as an idempotent no-op,must not recursively copy again。status=unsafe: The target is inside the source, or the source is inside the target; immediately stop the entire Phase 2, do not perform deletion/overwrite, and reportreasonand the two realpaths.status=error: The source is missing or path resolution fails; treat it as an incomplete deployment package and stop immediately.
This pre-check must not be replaced by a string prefix, an unexpanded relative path, or "it doesn't look like the same directory"; symlinks/aliases must be judged by realpath. File-level replace may continue to follow the existing atomic write rules; all recursive directory copies must pass through this gate item by item.
TRAE ownership and backup gate (target_cli contains trae when): before modifying any existing .trae/ file, first back up the original files that will be modified this time by relative path to .trae/.oh-story-backups/<UTC时间戳>/; the directory backup itself must also first run copy-path-safety.py. Only replacement is allowed for canonical Chinese main-package skill / command / agent / rule / AGENTS managed blocks bearing the oh-story-managed marker, for story_trae_hook.jswhose header comment explicitly identifies it as the oh-story TRAE adapter, and for story_hook_core.jsthat satisfies any of the following ownership evidence: contains the generic marker oh-story-managed: shared-hook-coretrue scripts/trae-core-ownership.py ; after validation with references/trae/legacy-managed-sha256.jsonthe sha256 matches the sole authoritative SKILL.md true metadata.openclaw.source points to this repository, or is precisely marked <!-- oh-story-managed: skill/{name} -->. User files with the same name but no ownership evidence must be retained and reported as conflicts, and must not be overwritten..trae/hooks.json is always merged by the helper according to a stable command identity, and the entire file is never replaced. Newly created artifacts must be written with the corresponding management marker, so that they can be safely upgraded next time.
TRAE and Claude Hook deduplication gate: TRAE will compatibly read the project .claude/settings*.json. Claude settings commands keep the cross-platform-executable direct bash ... form, without embedding POSIX if; all Claude shell entry points, after source lib/common.sh , are detected by the shared library as TRAE_PROJECT_DIR and exit successfully and silently. Execute as usual in Claude, and in the TRAE process let .trae/hooks.json execute exclusively. After deployment, verify with synthetic input from both sides that the same event produces only one set of oh-story output; "the two prompts look the same" must not be treated as acceptable.
WorkBuddy ownership and Hook mutual-exclusion gate (target_cli contains workbuddy when): only replace canonical Chinese main-package skill / command / agent / rule / CODEBUDDY (or AGENTS) managed blocks bearing the oh-story-managed marker, as well as hook files with adapter header comments or the generic shared-core marker; Skill directories use the same dual evidence of repository metadata / <!-- oh-story-managed: skill/{name} --> as TRAE. User files with the same name are retained and reported as conflicts..codebuddy/settings.json merges only through merge-workbuddy-settings.py . If the current skill comes from an enabled oh-story CodeBuddy plugin (the actual execution path is located at the plugin installation root, or the current session registry / codebuddy plugin list explicitly shows that oh-story is enabled), plugin hooks are loaded automatically; at this point the empty template must be used to remove the old oh-story-managed hook registrations in the project, and project-hooks.jsonmust no longer be merged; only in project-local skills mode are project hooks written, to prevent double triggering of the same event. The presence of .codebuddy-plugin/plugin.json in the repository or the fact that the plugin was once installed does not count as evidence that it is "currently enabled".
WorkBuddy namespace gate: plugin mode exposes Skills, Agents and Hooks only through .codebuddy-plugin/plugin.json ; it must not simultaneously expose Commands with the same names as Skills in the manifest, otherwise /oh-story:story-* will have component name competition. Plugin mode invokes namespace-qualified Skills such as /oh-story:story、/oh-story:story-long-write ; only after running story-setup does project mode expose via .codebuddy/commands/ true /story、/story-long-write and other bare commands. The two modes must be documented separately in the installation report; bare commands must not be described as plugin commands.
| Source path | Target path | Owner class | Merge mode | Validation check |
|---|---|---|---|---|
skills/story-setup/references/templates/CLAUDE.md.tmpl |
CLAUDE.md |
user+managed | marker/section merge | contains story skill routing sections |
skills/story-setup/references/templates/hooks/ |
.claude/hooks/ |
story-setup managed | recursive replace | session-*.sh, detect-story-gaps.sh, validate-story-commit.sh, guard-outline-before-prose.sh, check-prose-after-write.sh, story_hook_core.js, story_hook_cli.js, lib/common.sh, lib/sentinel.sh exist;story_hook_core.js byte-identical to the OpenCode/ZCode copy |
skills/story-setup/references/templates/rules/*.md |
.claude/rules/*.md |
story-setup managed | replace | every rule contains paths frontmatter |
skills/story-setup/references/templates/agents/*.md |
.claude/agents/*.md |
story-setup managed | replace | 8 agent files exist |
skills/story-setup/references/agent-references/*.md |
.claude/skills/story-setup/references/agent-references/*.md |
story-setup managed | replace | every story-setup/references/agent-references/*.md reference resolves |
skills/story-setup/references/templates/settings-hooks.json |
.claude/settings.local.json |
user+managed | replace managed registrations by stable hook identity | hook JSON valid; legacy matcher registrations migrated, one copy of each current template command, user hooks preserved |
skills/story-setup/scripts/merge-claude-settings.py |
executed at deployment time, not copied into the project | story-setup helper | execute | replace known story hook registrations, preserve user hooks/top-level fields, historical matcher migration and repeated execution idempotent |
skills/story-setup/references/templates/质检进度.md.tmpl |
{书名}/追踪/质检进度.md |
user state | create only if absent | never overwrite existing progress table |
| generated sentinel | .story-deployed |
story-setup managed | replace | contains agents_version, setup_skill_version, target_cli, resolver_strategy, references_dir |
skills/story-setup/references/opencode/AGENTS.md.tmpl |
AGENTS.md |
user+managed | marker/section merge | contains story skill routing sections |
skills/story-setup/references/opencode/agents/ |
.opencode/agents/ |
story-setup managed | replace | 8 agent files exist (before replace, cache existing ones per "Preserve existing model configuration" in "Configure OpenCode Agent Models" model:, to avoid overwriting user-configured models) |
skills/story-setup/references/opencode/plugin.ts |
.opencode/plugins/story-hooks.ts |
story-setup managed | replace | TypeScript plugin file exists |
skills/story-setup/references/opencode/story_hook_core.js |
.opencode/plugins/lib/story_hook_core.js |
story-setup managed | replace | Node syntax valid; byte-identical to the ZCode copy; imported by story-hooks.ts |
skills/story-setup/references/opencode/commands/ |
.opencode/commands/ |
story-setup managed | replace | command count matches the current OpenCode template manifest |
skills/story-setup/references/opencode/opencode.json.patch |
merge into opencode.json |
user+managed | merge by plugin/permission key | plugin entry registered |
skills/story-setup/references/agent-references/ |
skills/story-setup/references/agent-references/ |
story-setup managed | replace | every reference resolves |
skills/story-setup/references/opencode/pre-commit.sh |
.git/hooks/pre-commit |
user+managed | append or create | file exists and is executable; if it contains a marker block, replace the block contents; if not, detect the exit 0 position and insert intelligently |
skills/story-setup/references/codex/AGENTS.md.tmpl |
AGENTS.md |
user+managed | marker/section merge | contains Codex story skill routing sections |
skills/story-setup/references/codex/agents/ |
.codex/agents/ |
story-setup managed | replace | 8 TOML agent files parse and contain name/description/developer_instructions |
skills/story-setup/references/codex/hooks/hooks.json |
.codex/hooks.json |
user+managed | replace managed registrations by stable hook identity | hook JSON valid; all stale direct/launcher registrations removed, current 6 registrations present exactly once |
skills/story-setup/references/codex/hooks/{story_codex_hook.py,run-story-hook.sh,run-story-hook.cmd} |
.codex/hooks/ same-named file |
story-setup managed | replace | Python/shell/cmd launcher files complete |
skills/story-setup/scripts/merge-codex-hooks.py |
executed at deployment time, not copied into the project | story-setup helper | execute | replace known management registrations, preserve user hooks and unknown top-level fields, result idempotent |
skills/story-setup/scripts/copy-path-safety.py |
executed before each recursive directory copy, not copied into the project | story-setup helper | execute | same=no-op; ancestor/descendant nesting=block; only safe can be copied |
skills/story-setup/references/agent-references/ |
.codex/skills/story-setup/references/agent-references/ |
story-setup managed | replace | every reference resolves |
skills/story-setup/references/zcode/AGENTS.md.tmpl |
AGENTS.md |
user+managed | marker/section merge | contains ZCode $story-* routing and solo fallback |
canonical repository skills/{browser-cdp,story*}/ |
.zcode/skills/{browser-cdp,story*}/ |
story-setup managed for 18 known skill names | replace known skill dirs only | SKILL.md name set matches the Chinese main package's 18 Skill manifest and satisfies ZCode frontmatter restrictions |
skills/story-setup/references/zcode/commands/ |
.zcode/commands/ |
story-setup managed for 18 known command names | replace known command files only | commands have valid names/frontmatter and cover the canonical skill list |
skills/story-setup/references/zcode/hooks/story_zcode_hook.js |
.zcode/hooks/story_zcode_hook.js |
story-setup managed | replace | Node syntax valid; hook contract tests pass |
skills/story-setup/references/zcode/hooks/story_hook_core.js |
.zcode/hooks/story_hook_core.js |
story-setup managed | replace | Node syntax valid; hook contract tests pass |
skills/story-setup/references/zcode/config.json.patch |
merge into .zcode/config.json |
user+managed | merge by event+matcher+process args | JSON valid; validated per the hooks mutual-exclusion branch in step 4 of the "ZCode Deployment Algorithm"—when the oh-story plugin is not installed hooks.enabled=true, only supported events; when the plugin is installed, validate .zcode/config.json does not contain (or has removed) this batch of oh-story hooks registrations |
skills/story-setup/references/trae/AGENTS.md.tmpl |
AGENTS.md |
user+managed | marker/section merge | contains TRAE Code story routing and fallback contract |
canonical repository skills/{browser-cdp,story*}/ |
.trae/skills/{skill-name}/ |
story-setup managed for the fixed 18 source names | backup + replace managed dirs only | target SKILL.md count/names match the Chinese main package's 18 Skill manifest; if source and target are the same, no-op |
skills/story-setup/references/trae/commands/ |
.trae/commands/{skill-name}.md |
story-setup managed by oh-story-managed marker |
backup + replace 18 managed files only | each canonical skill has exactly one same-named command, frontmatter contains name / description |
skills/story-setup/references/trae/agents/ |
.trae/agents/ |
story-setup managed by oh-story-managed marker |
backup + replace exact common roster (8 files) | name set exactly chapter-extractor, character-designer, consistency-checker, narrative-writer, revision-governor, story-architect, story-explorer, story-researcher; TRAE frontmatter parseable |
repository skills/story-data-analyze/agents/trae/ |
.trae/agents/ |
story-setup managed by oh-story-managed marker |
backup + replace exact data roster (5 files) | name set exactly story-data-fetcher, story-data-method-validator, story-data-metrics-analyst, story-data-supervisor, story-data-text-improvement-planner; no duplicate names with common roles |
skills/story-setup/references/trae/rules/ |
.trae/rules/ |
story-setup managed by oh-story-managed marker |
backup + replace managed files only | rules frontmatter contains alwaysApply / globs |
skills/story-setup/references/trae/hooks/{story_trae_hook.js,story_hook_core.js} |
.trae/hooks/ same-named file |
runner by adapter header; core by fixed name + packaged hash | backup + replace managed files only | Node syntax valid; shared core consistent with other adapter copies |
skills/story-setup/references/trae/hooks/hooks.json |
.trae/hooks.json |
user+managed | replace managed registrations by stable hook command identity | version: 1; contains only TRAE-supported events; user hook/top-level fields preserved |
skills/story-setup/scripts/merge-trae-hooks.py |
executed at deployment time, not copied into the project | story-setup helper | execute | migrate legacy matcher/command, preserve user configuration, repeated execution byte-idempotent |
skills/story-setup/scripts/trae-core-ownership.py + references/trae/legacy-managed-sha256.json |
executed at deployment time, not copied into the project | story-setup ownership helper/registry | classify before replace | marker / legacy SHA judged managed; unknown/error preserved and reported |
skills/story-setup/references/workbuddy/CODEBUDDY.md.tmpl |
existing CODEBUDDY.md / .codebuddy/CODEBUDDY.md, or when neither exists, AGENTS.md / .codebuddy/CODEBUDDY.md |
user+managed | per "WorkBuddy memory merge strategy", merge only the marker block | does not shadow existing AGENTS; conditional import placeholders resolved; management block unique |
canonical repository skills/{browser-cdp,story*}/ |
.codebuddy/skills/{skill-name}/ |
story-setup managed for the fixed 18 source names | replace managed dirs only | SKILL.md name set matches the Chinese main package's 18 Skill manifest; if source and target are the same, no-op |
skills/story-setup/references/workbuddy/commands/ |
.codebuddy/commands/{skill-name}.md |
story-setup managed by oh-story-managed marker |
replace 18 managed files only | commands correspond one-to-one with canonical skills, frontmatter uses only CodeBuddy-supported fields |
skills/story-setup/references/workbuddy/agents/ |
.codebuddy/agents/ |
story-setup managed by marker | replace exact common roster (8 files) | name set exactly chapter-extractor, character-designer, consistency-checker, narrative-writer, revision-governor, story-architect, story-explorer, story-researcher; WorkBuddy frontmatter is valid, and project Agent names do not carry a plugin namespace |
repository skills/story-data-analyze/agents/workbuddy/ |
.codebuddy/agents/ |
story-setup managed by marker | replace the exact data physical roster (2 files) | the name set is exactly story-data-fetcher, story-data-readonly-runner; the 4 logical role cards remain in Skill references |
skills/story-setup/references/workbuddy/rules/ |
.codebuddy/rules/ |
story-setup managed by marker | replace managed files only | alwaysApply is parseable; user rules are preserved |
skills/story-setup/references/workbuddy/hooks/{story_workbuddy_hook.js,story_hook_core.js} |
.codebuddy/hooks/ files with the same name |
story-setup managed | replace managed files only | Node syntax valid;shared core byte-parity |
skills/story-setup/references/workbuddy/hooks/project-hooks.json |
merge into .codebuddy/settings.json |
user+managed | merge or remove by plugin mutex | only project-local mode registers once each; plugin mode is zero; user settings and hooks are preserved |
skills/story-setup/scripts/merge-workbuddy-settings.py |
executed at deployment time, not copied into the project | story-setup helper | execute | stable runner identity removal of old entries, merge/removal is idempotent |
skills/story-setup/references/openclaw/AGENTS.md.tmpl |
AGENTS.md |
user+managed | marker/section merge | contains OpenClaw story skill routing sections |
skills/story-setup/references/generic/AGENTS.md.tmpl |
AGENTS.md |
user+managed | marker/section merge | contains generic story skill routing sections |
skills/story-setup/references/reasonix/AGENTS.md.tmpl |
AGENTS.md |
user+managed | marker/section merge | contains Reasonix story skill routing sections and solo/direct fallback |
canonical repository skills/{browser-cdp,story*}/ |
skills/{browser-cdp,story*}/ |
story-setup managed for 18 known skill names | replace known skill dirs only | SKILL.md the name set matches the 18-Skill list of the Chinese main package; the OpenClaw branch validates frontmatter compatibility |
skills/story-setup/references/agent-references/ |
skills/story-setup/references/agent-references/ |
story-setup managed | replace via full skill copy | every reference resolves |
opencode.json merge algorithm
When deploying opencode.json.patch , merge according to the following rules:
- Read the existing
opencode.json(if present), parse the JSON - Merge the
pluginarray: add./.opencode/plugins/story-hooks.tsto the array and deduplicate - Preserve other configuration fields the user already has (
permission、model、provider, etc.), do not overwrite - Write the merged
opencode.json
Step 2: Deploy CLAUDE.md
- Read
skills/story-setup/references/templates/CLAUDE.md.tmpl - Replace placeholders (see the "Template placeholders" section below)
- Write to the project root
CLAUDE.md(if it already exists, handle it according to the "CLAUDE.md merge strategy")
Step 3: Deploy Hooks
- Recursively copy the complete directory tree: copy
skills/story-setup/references/templates/hooks/to the user project.claude/hooks/ - The subdirectory
lib/must be preserved, where:lib/common.shprovidesproject_root、discover_active_book、discover_all_bookslib/sentinel.shprovides.story-deployedfield reading
- Only set execute permission for
.claude/hooks/*.sh(chmod +x);lib/*.shis handled by the hooksource, the executable bit is not required
Step 4: Deploy Rules
- Read all
skills/story-setup/references/templates/rules/files under.mdfiles - Copy to the user project's
.claude/rules/directory
Step 5: Deploy Agents
- Read all
skills/story-setup/references/templates/agents/files under.mdfiles - Copy to the user project's
.claude/agents/directory - Agent files are story-setup managed files and can be safely overwritten; on version upgrades, redeploy according to
UPGRADING.md's version detection result target_cliWhen opencode is included, overwrite.opencode/agents/, first execute Step 1 of "Configure OpenCode Agent model" below to cache the existingmodel:. That step is written later in this section, but it must be run first—reading in order and doing what you read would overwrite before caching, and the user's already configured models would be lost.- A new session must be started after deployment: agents are only registered at session startup; for the reason and the report text that must be output, see "Output installation report" in "Verify installation".
Agent compatibility handling
- Agent frontmatter is primarily based on Claude Code; OpenCode's
.opencode/agents/*.md, Codex's.codex/agents/*.toml, TRAE's.trae/agents/*.mdand WorkBuddy's.codebuddy/agents/*.mdall use pre-generated artifacts under the corresponding adapter, and frontmatter from other clients must not be copied directly. The only source for the TRAE general role isreferences/trae/agents/, the only source for the data analysis role isskills/story-data-analyze/agents/trae/; the corresponding sources for WorkBuddy arereferences/workbuddy/agents/andskills/story-data-analyze/agents/workbuddy/. Do not mechanically carry over Claude model aliases or proprietary fields from one side to the other. OpenCode/Codex/WorkBuddy pre-generated artifacts are generated by repository maintenance scripts; these scripts are not distributed with story-setup, and deployment only copies committed artifacts. - ZCode 3.3.4 does not deploy project agents: its custom sub-agents only support user-level
~/.zcode/agents/, and the plugin manifest'sagentsis currently not executed. Do not create.zcode/agents/or modify the user home; related Skills must go directly solo/direct and report fallback. - OpenClaw Phase 1 does not deploy agents: OpenClaw only deploys skills; skills related to agent collaboration must be downgraded to solo/direct according to the existing fallback rules. Do not directly copy Claude/OpenCode agent frontmatter into an OpenClaw agent.
- After deployment to the project, reference materials referenced within an agent must use the
story-setup/references/agent-references/*.mdcopy path within this same skill; do not reference other skills' references across skills. Each adapter only uses the current canonical prefix: for Claude Code it is.claude/skills/, for OpenCode / OpenClaw / Reasonix / generic it isskills/, for Codex it is.codex/skills/, for ZCode it is.zcode/skills/, for TRAE Code it is.trae/skills/, for WorkBuddy / CodeBuddy Code it is.codebuddy/skills/; in plugin mode, the platform-inlined${CODEBUDDY_PLUGIN_ROOT}/skills/may be used. Do not traverse historical alternative paths at runtime.
Deploy Agent References
- Copy all
skills/story-setup/references/agent-references/under.mdinto the project's.claude/skills/story-setup/references/agent-references/ - Validation: wherever
story-setup/references/agent-references/<file>.mdappears in an agent or reference, both the source package and the target package must have<file>.md
Deploy Codex Agents (when target_cli includes codex)
- Read all
skills/story-setup/references/codex/agents/under.tomlfiles and copy them to the user project's.codex/agents/ - Agent files are story-setup managed files and can be safely overwritten;
references/codex/agents/the TOML in is deterministically generated from the Claude agent template by the repository root'sscripts/generate-codex-agents.pyand committed to the repository; deployment only copies - Validate that every TOML can be parsed and contains the fields required by Codex:
name、description、developer_instructions - Read-only responsibility agents (
chapter-extractor、consistency-checker、revision-governor、story-explorer) must retainsandbox_mode = "read-only" - After deployment you must trust + open a new Codex session(for the report wording and fallback rules, see "Verify Codex Deployment"); if the runtime returns
unknown agent_type, the caller must downgrade to solo/direct and report fallback. - Synchronously copy
skills/story-setup/references/agent-references/to.codex/skills/story-setup/references/agent-references/as the primary in-project reference path for Codex agents
Deploy TRAE Agents (when target_cli includes trae)
- First validate that the name set of
references/trae/agents/is exactlychapter-extractor,character-designer,consistency-checker,narrative-writer,revision-governor,story-architect,story-explorer,story-researcher(8 general cards), then validate that the name set of canonicalstory-data-analyze/agents/trae/is exactlystory-data-fetcher,story-data-method-validator,story-data-metrics-analyst,story-data-supervisor,story-data-text-improvement-planner(5 data cards). The two groups must have no duplicate names, and after merging the roster must be exactly 13 cards; if any required directory is missing, empty, has a name set mismatch, has duplicate names, or has unparseable frontmatter, stop the TRAE branch and do not perform a partial deployment. - Write in sequence
.trae/agents/, only create or replace same-named files with the<!-- oh-story-managed: agent/<agent-name> -->marker; same-named files without the marker are retained and reported. Do not delete other user agents. - TRAE frontmatter only uses its native fields:
name、description, the comma-separated string form oftools/disallowedToolsand the optional TRAE built-inmodel; it is forbidden to automatically write in Claude model aliases. - After deployment, prompt the user to start a new TRAE session and confirm that the Subagents Beta feature is available. If the current TRAE version/session does not support native Agents, you must degrade according to each skill's contract
solo/direct, reportFallback: TRAE subagent unavailable -> solo/direct; do not claim that the full/lean multi-Agent setup is in effect.
Deploy WorkBuddy Agents (when target_cli includes workbuddy)
- First verify that the name set of
references/workbuddy/agents/is exactlychapter-extractor,character-designer,consistency-checker,narrative-writer,revision-governor,story-architect,story-explorer,story-researcher(8 general cards); then verify that the physical name set ofskills/story-data-analyze/agents/workbuddy/is exactlystory-data-fetcher,story-data-readonly-runner(2 data cards), and that the four read-only logical role cards remain intact in that Skill's WorkBuddy role-card references. All physical names must have no duplicates, and after merging, the Chinese main package's physical name roster must be exactly 10 cards. - CodeBuddy currently, during the
agenticregistry query phase, hard-caps the total number of built-in + project Subagents at 20. The exact 10 physical WorkBuddy cards listed in this section are below the platform limit; the deployer does not inject project extension cards into that roster, and does not hide capacity issues through sorting or truncation. - Each Markdown must have valid YAML frontmatter,
namemust match the filename,descriptionmust be non-empty,tools/disallowedToolsmust be a comma-separated string and use only current CodeBuddy tool names. plugin agents are prohibited fromhooks、mcpServers、permissionMode; project agents also do not depend on these fields. - Only create or replace those marked with
<!-- oh-story-managed: agent/<name> -->marked.codebuddy/agents/<name>.md; files with the same name that are unmarked are kept and the conflict is reported. Project definitions take precedence over plugin/user agents; project mode uniformly uses bare names andAgent(subagent_type: "<name>")。 - pooled runner logical role cards remain within the owning Skill and must not be copied into
.codebuddy/agents/. The main coordinator must select the runner according to that Skill's runtime mapping, and pass in the promptlogical_role, the absolute path of the role card, the project root, the input isolation contract, and the task body; the runner must fully read and verify the role card before executing. - In plugin-only mode, the UI name is
oh-story:<name>; only use it when the current registry actually exposes that name. When story-setup has not been run, do not guess from the on-disk manifest that the registry has loaded it; if the call fails, immediately degrade according to the Skill contract. After project deployment is complete, uniformly use.codebuddy/agents/'s bare name to avoid namespace divergence. - After deployment, start a new WorkBuddy / CodeBuddy session and use
/agentsor the current registry to confirm that all exact 10 physical cards listed in this section are visible; then smoke-test one general Agent and one pooled runner logical role separately. Child Agents must not recursively spawn.
Configure OpenCode Agent models
Execute only when
target_cliincludesopencode. When an OpenCode subagent does not specify a model, it inherits the main model, causing low-cost Agents to also consume the main model's quota. This step automatically detects the user's model and writes it to themodel:field.
Step 1: Preserve the existing model configuration (must be executed before the replace of .opencode/agents/ )
OpenCode agents deployment is replace, and will overwrite the previously written model:. So before executing that replace beforefirst scan the existing .opencode/agents/*.md, and cache each agent's model:(agent name → model ID). If subsequent detection fails/times out, or the user skips a tier, backfill with the cached value to avoid overwriting the user's previously configured low-cost model with the main model. If replace has already occurred and the cache is empty, treat it as a fresh deployment and note "failed to preserve the previous model configuration" in the installation report.
Step 2: Get model list
Preferentially execute opencode models --verbose, which outputs metadata including cost (input/output/cache unit price), context, and capabilities; if unavailable or parsing fails, fall back to opencode models plain text (each line provider/model). Both use a 60000ms (60 second) timeout, because the first run needs to load the models.dev cache.
- Success → proceed to "Model Tiering"
- Timeout → retry once (the cache may not be warmed up); if it still times out, backfill the existing
model:from the "preserve existing model configuration" cache, skip automatic configuration, and output a manual configuration guide in the installation report - Failure (command does not exist, output is empty, etc.) → same as above: backfill the "preserve existing model configuration" cache, skip automatic configuration, and output a manual configuration guide
Step 3: Model tiering
Prefer tiering by cost (when --verbose is present): tier by each model's actual cost from low to high—the low tier takes the cheapest/free tier, the mid tier takes the mid-priced tier, and the high tier takes the most expensive or the tier with the strongest context/capabilities. Free models are classified as low tier based on their real cost=0,not based on marketing words in the name(e.g., nemotron-3-ultra-free has ultra in its name but cost=0, so it should be classified as low tier). Models without cost data also enter the candidates on this basis and are not discarded.
Fall back to tiering by keywords (when there is no --verbose or no cost): take the model name after the last / in the model ID and split it by -、.、_ into segments, then exactly match keywords segment by segment (case-insensitive). For example, minimax-m3 is split into [minimax, m3], which matches neither mini nor max;claude-haiku-4.5 is split into [claude, haiku, 4, 5], which matches haiku. Keyword tiering is heuristic; in the installation report, label 分级依据:关键词(heuristic)。
| tier | matching keyword | corresponding Agent |
|---|---|---|
| low tier | haiku, flash, mini, nano, lite |
chapter-extractor, consistency-checker, story-explorer |
| mid tier | sonnet, plus |
story-researcher, narrative-writer, character-designer, revision-governor |
| high tier | opus, pro, ultra, max |
story-architect |
- A model may match keywords for multiple tiers; take the highest tier
- Under keyword fallback, models that do not match any keyword are still included in the candidates as additional suggestions (under cost tiering, all are included), and are listed in the installation report with the note "can be used via custom input"
- Within the same tier, if multiple model providers are included, prioritize listing models from well-known providers (anthropic, openai, google, deepseek)
Step 4: Tier-by-tier interactive selection
In the order low tier → mid tier → high tier, use AskUserQuestion at each tier to let the user choose.
Low tier option structure:
问题:"为低成本 Agent(chapter-extractor, consistency-checker, story-explorer)选择模型:"
选项:
- provider/model-id
- provider/model-id
- 自定义输入(手动输入完整模型 ID,ID 拼写错误要到运行时才会暴露)
- 跳过,使用主模型(成本可能较高)
Mid tier option structure:
问题:"为写作质量关键 Agent(narrative-writer, character-designer, story-researcher, revision-governor)选择模型:"
选项:
- provider/model-id
- provider/model-id
- 自定义输入(请勿使用低端模型,会影响正文质量;ID 拼写错误要到运行时才会暴露)
- 跳过,使用主模型(主模型质量通常足够)
High tier option structure:
问题:"为总指挥 Agent(story-architect)选择模型:"
选项:
- provider/model-id
- provider/model-id
- 自定义输入(手动输入完整模型 ID,ID 拼写错误要到运行时才会暴露)
- 跳过,使用主模型(成本可能较高)
Rules:
- Show at most 5 candidates; if there are more, truncate and prompt "for more models, please use custom input".At each tier, regardless of whether the number of candidates is 0, pop up AskUserQuestion, and the options must include at least: candidate models (if any),
自定义输入、保留现有模型(cache the "preserve existing model configuration" to that agent's model; if none, do not show this item),跳过,用主模型. Even when the candidate count is 0, still show the prompt, and include the corresponding warning in the question description + list ungraded/ungrouped models for reference—no longer silently skip the interaction (otherwise the user cannot reach the custom input). 自定义输入: user entersprovider/model-idfull ID; before writing, validate that it is a single line, contains no control characters, and matches^[A-Za-z0-9._-]+/[A-Za-z0-9._:+-]+$; if it does not match, prompt for re-entry or choose to skip.保留现有模型: write back the cached agent model for "keep existing model config" (preserve the user's previous config on redeploy); this does not count as "skip".跳过,用主模型: explicitly clear—do not write the agent'smodel:; the agent inherits the main model. To keep the previous config, choose保留现有模型。- When the candidate count for any tier is 0, include a hint in the question description:
- low tier: "No low-cost model detected; these 3 agents will use the main model, costs may be higher"
- mid tier: "No matching mid-tier model detected. narrative-writer, character-designer, story-researcher will use the main model. If the main model's quality is sufficient, this config is reasonable; if you need to reduce cost, use custom input to specify a mid-tier model no lower than the main model's quality, or choose from the ungraded models below."
- high tier: "No high-tier model detected; story-architect will use the main model"
Step 5: write the model field
the agent file corresponding to the user's choice (.opencode/agents/*.md, already deployed before this step by the OpenCode agents deployment step in the deploy manifest), at the end of the frontmatter, before the closing --- , usinga zero-indentation top-level fieldinsert model:(do not insert it inside the indented block of a multi-line map such as permission: ). If the value contains YAML special characters, quote it to ensure the frontmatter is not broken:
---
description: ...
mode: subagent
permission:
read: allow
edit: deny
steps: 12
model: provider/model-id
---
- If the agent file already has a
model:field (redeploy scenario), replace the value of that top-levelmodel:; do not add a duplicate key 保留现有模型: write back the cached agent model for "keep existing model config"跳过,用主模型: do not write themodel:field- Detection failure/timeout, or tiers that did not reach this step: use the "keep existing model config" cache to backfill
model:, to avoid replace wiping out the user's previous config
Step 6: deploy the QC progress template
追踪/上下文.mdis no longer deployed by this step. It has been changed to a derived view of_tracking-state.json, rendered on commit by the tracking transaction tool bundled with the writing skill; story-setup no longer creates or overwrites it- read
skills/story-setup/references/templates/质检进度.md.tmpl - Only when it has been identified as a long-form book list and
{书名}/追踪/already exists, create the missing{书名}/追踪/质检进度.md - If the target file already exists, do not overwrite; a short-form project must not create
追踪/directory because of this. This table is the mechanically checkable record required by Phase 5 (consistency-checker, independent AI-flavor review), and must not be missing just because the project is already being written
Step 7: merge Hooks registration into settings.local.json
- Detect Python per the existing cross-platform rules:
for PYBIN in python3 python py; do "$PYBIN" -c "" 2>/dev/null && break; done; if no usable interpreter is found, stop; do not hand-write or simplify the merge. - Call
"$PYBIN" "{story-setup skill目录}/scripts/merge-claude-settings.py" --existing "{项目}/.claude/settings.local.json" --template "{story-setup skill目录}/references/templates/settings-hooks.json" --output "{项目}/.claude/settings.local.json"。 - The helper removes all historical registrations of known story-setup hooks, then appends the current template; therefore matcher, timeout, and if can upgrade with versions, while user hooks and unknown top-level fields mixed into old blocks are preserved as-is. After writing, parse the JSON, verify that there is one copy of each template command and that user config remains, then rerun the helper and compare file bytes to confirm idempotence.
Codex hooks.json merge algorithm (when target_cli contains codex)
Codex project hooks are deployed to .codex/hooks.json; the runtime script is deployed to .codex/hooks/story_codex_hook.py、run-story-hook.sh、run-story-hook.cmd. JSON is only responsible for locating the project root and passing the event; interpreter detection is handled uniformly by the platform launcher.
- Locate the current story-setup skill directory, read
references/codex/hooks/hooks.jsonas the sole current template, read the project's.codex/hooks.json(treated as an empty object if it does not exist). - Detect available Python according to the existing cross-platform rules:
for PYBIN in python3 python py; do "$PYBIN" -c "" 2>/dev/null && break; done; if no usable interpreter is found, stop; do not hand-write or simplify the JSON merge. - Invoke
"$PYBIN" "{story-setup skill目录}/scripts/merge-codex-hooks.py" --existing "{项目}/.codex/hooks.json" --template "{story-setup skill目录}/references/codex/hooks/hooks.json" --output "{项目}/.codex/hooks.json". This helper recognizes the old direct-callstory_codex_hook.py, the currentrun-story-hook.sh, andrun-story-hook.cmdmanagement identities; it first removes all known management registrations, then appends the current template. - Preserve the user's existing non-story-setup hooks, matcher blocks, and unknown top-level fields. Repeated execution must be idempotent; do not append and deduplicate again by the raw
commandstring, otherwise the v17 direct-call command will be double-registered with the v18 launcher. - After writing, parse the JSON to verify: the old direct-call
story_codex_hook.pycommand count is 0, each of the current template's 6 registrations exists exactly once, and user hooks and unknown top-level fields are still present. Then prompt the user: the project.codex/layer needs to be trusted by Codex, and non-managed command hooks also need to be reviewed/trusted in/hooksbefore they will run; on Windows usecommandWindows, and the launcher locates the project.codex/hooks/upward from the current directory, consistent with the nested-directory behavior of POSIX paths.
Deployment source resolution (prevent self-copying from an old project copy)
- Record the currently executing
story-setupdirectory and its parent skills root, calledbootstrap_root. If it is located under the target project's.trae/skills/、.codebuddy/skills/、.zcode/skills/、.codex/skills/、.claude/skills/or rootskills/, it is merely a "deployed snapshot" and must not be treated wholesale as the authoritative upgrade source. - For a deployed project, additionally enumerate these verifiable candidates: the currently enabled plugin's
${CODEBUDDY_PLUGIN_ROOT}/skills/story-setup、~/.agents/skills/story-setup、~/.claude/skills/story-setup、~/.codex/skills/story-setup, as well as the local installation directory explicitly provided by the user this time. Do not search the entire disk, and do not directly execute unverified content from web pages or floating repositories. - A candidate is valid only when all of the following conditions hold:
SKILL.mdfrontmatter'sname=story-setup、versionis a comparable three-part numeric SemVer,metadata.openclaw.sourcepoints to this oh-story repository, and all references and helper self-checks listed in Phase 1 pass. Invalid candidates are only reported; do not read other content. - Among valid candidates and
bootstrap_root, select the latest complete package by SemVer ascanonical_root; when versions are equal, prefer the installation package outside the project, and an external package with a lower version must not be used to downgrade the project. The installation report must statebootstrap_root、canonical_root, their respective versions/purposes, and the reason for selection. - Subsequent templates, helpers, and the 18 Chinese main-package Skills are all read from
canonical_root; project-custom Skills do not enter the TRAE/WorkBuddy adaptation deployment source for this round, and existing user Skills are left untouched. copy-path-safety.py'sstatus=sameonly makes that one current source/target item a no-op; do not skip refreshing other Skills, Commands, Agents, Rules, and Hooks fromstory-setupjust because the project'scanonical_rootcopy points to itself.
canonical Chinese main-package Skill list (shared by all skills copy branches)
canonical_root/skills/must exactly contain these 18 deployable Skills:browser-cdp、story、story-cover、story-data-analyze、story-deslop、story-explore、story-import、story-long-analyze、story-long-scan、story-long-write、story-publish、story-release-package、story-research、story-review、story-setup、story-short-analyze、story-short-scan、story-short-write。- Read each according to the above fixed name set
SKILL.mdfrontmatter'sname/description; if any is missing, the directory name is inconsistent withname, or there are duplicate names, stop deployment. Do not expand the main package because extrastory*directories appear at the project root. - For each source Skill directory and the corresponding target directory, execute item by item
copy-path-safety.py;samerecord as no-op,unsafe/errorstop, onlysafemay be copied. Do not delete or wholesale replace the entire user skills root directory.
TRAE / WorkBuddy fixed Agent roster
- The common roster shared by both ends is exactly 8 cards:
chapter-extractor,character-designer,consistency-checker,narrative-writer,revision-governor,story-architect,story-explorer,story-researcher。 - The TRAE data roster is exactly 5 cards:
story-data-fetcher,story-data-method-validator,story-data-metrics-analyst,story-data-supervisor,story-data-text-improvement-planner. The TRAE physical roster must be exactly equal to the union of the aforementioned 8 common cards and these 5 data cards, 13 cards in total. - The WorkBuddy data physical roster is exactly 2 cards:
story-data-fetcher,story-data-readonly-runner. The WorkBuddy physical roster must be exactly equal to the union of the aforementioned 8 common cards and these 2 data cards, 10 cards in total. The four read-only logical role cards are deployed along with the data analysis Skill itself, located via its runtime mapping, and are not registered as physical Agents. - Both ends only back up/replace the above exact marker cards, preserving user Agents; cards that were managed last time but are not in the corresponding exact name set this time go through "managed asset convergence": back up then delete.
ZCode deployment algorithm (when target_cli includes zcode)
ZCode's first version deploys Skills, Commands, AGENTS.md, and Hooks within supported events; it does not deploy .zcode/agents or .zcode/rules。
- Copy to
.zcode/skills/{skill-name}/according to the "canonical Chinese main package Skill list"; only replace these 18 known directories, preserving the user's other Skills. - Copy
references/zcode/commands/*.mdto.zcode/commands/; only replace management commands with the same name as canonical skills, preserving the user's other Commands. If a skill in the main package lacks a pre-generated template, consider the package incomplete and stop; do not temporarily generate commands as project extensions. - Copy
references/zcode/hooks/story_zcode_hook.jsandreferences/zcode/hooks/story_hook_core.jsto.zcode/hooks/。 - Read
references/zcode/config.json.patchand the existing.zcode/config.json(if only rootzcode.json, still create.zcode/config.jsonto host oh-story project Hooks, without rewriting the root file):- Preserve all user unknown fields, MCP, plugins, skills/commands disable overrides;
- hooks are mutually exclusive (to avoid double triggering): if this project runs via an already-installed oh-story plugin (marketplace install, repository root
.zcode-plugin/plugin.json'shooks.jsonhas globally registered SessionStart/PreToolUse/PostToolUse), thenskipbelow mergeconfig.json.patch'shooksblock into.zcode/config.json——the plugin manifest has already registered these hooks, and merging again would run the same event twice (PreToolUse intercepts twice, PostToolUse injects twice). Only merge hooks when the plugin is not installed (direct clone / manual import of references). When uncertain, use "whether ZCode has already registered this set of hooks via this plugin" as the standard; skills/commands/hook files/AGENTS and the non-hook fields of config are deployed as usual on both paths. - Merge hooks (only when the plugin is not installed): set
hooks.enabled: true; if the user already has a largertimeoutMsthen keep it, otherwise take the template value; forhooks.events's SessionStart, PreToolUse, PostToolUse, followevent + matcher + process command + argsDeduplicate and append; do not copy PreCompact, PostCompact, SessionEnd, or SubagentStop, which ZCode does not support, nor Notification.
- Write
references/zcode/AGENTS.md.tmplinto the rootAGENTS.md。 .story-deployedoftarget_cliwritezcodeor a multi-target combination,references_dirwrite.zcode/skills/story-setup/references/agent-references。- The installation report clearly states: ZCode 3.3.4 project/plugin custom agents do not execute, and all specialized roles go through solo/direct; the system needs an available
nodecommand to run project Hooks.
Plugin installation does not go through this algorithm: repository root .zcode-plugin/plugin.json directly exposes the same set of Skills/Commands/Hooks. Plugin Skills have lower priority than workspace .zcode/skills; when both exist, the project snapshot takes precedence, and upgrading the project snapshot requires rerunning $story-setup。Hooks can only be registered once: the plugin manifest and workspace .zcode/config.json register the same batch of events, so once the plugin is installed, do not merge the hooks of config.json.patch into .zcode/config.json(see the hooks mutual exclusion in step 4 of the above algorithm), otherwise PreToolUse/PostToolUse will trigger twice; when the plugin is present, the plugin manifest is the sole registration source for hooks.
TRAE hooks.json merge algorithm (when target_cli includes trae)
- Read
references/trae/hooks/hooks.jsonas the sole current template, and read project.trae/hooks.json(treated as an empty object when absent). The valid TRAE schema is top-level{ "version": 1, "hooks": {...} }, event values are matcher group arrays, within a group arematcher+hooks, and each hook uses only{ "type": "command", "command": "<单一 shell command 字符串>", "timeout": <秒> }。 - Detect according to cross-platform rules
python3/python/py; when no usable interpreter is available, stop the TRAE branch, and do not hand-write or wholesale overwrite the JSON. - Invoke
"$PYBIN" "{story-setup skill目录}/scripts/merge-trae-hooks.py" --existing "{项目}/.trae/hooks.json" --template "{story-setup skill目录}/references/trae/hooks/hooks.json" --output "{项目}/.trae/hooks.json". The helper recognizes only registrations whose command contains.trae/hooks/story_trae_hook.jsas oh-story managed items: first remove them from historical event/matcher blocks, then append the current template. User hooks in the same matcher block, other events, and unknown top-level fields are all preserved. - Validate after writing
version == 1; event names may only come from the TRAE supported setSessionStart、UserPromptSubmit、PreToolUse、PostToolUse、Stop、Notification, and the current template must not containSessionEnd、PreCompact、PostCompact、SubagentStop; within hooks, ZCode'sprocess/args/timeoutMsor Claude'sifmust not appear. Body tool matchers cover TRAE nativeRunCommand|Write|Edit, commit advisory coversRunCommand。 - Verify that each oh-story command identity in the template appears exactly once in the result, and that user hooks/top-level fields are still present; running the helper again must produce byte-identical output to the previous run.
TRAE Code native deployment algorithm (when target_cli includes trae)
The TRAE branch deploys native Skills / Subagents / Commands / Rules / Hooks, and does not use the generic skills-only degraded mode.
- Confirm the fixed 18 Skills according to the "canonical Chinese main package Skill list". Before any writing, establish UTC-timestamped backups for the existing managed assets to be modified this time according to the "TRAE ownership and backup gate"; upon encountering files with the same name but without the
oh-story-managedmarker, retain them, record the conflict, and stop writing that asset. - After passing each item through
copy-path-safety.py, copy the 18 canonical Skills to.trae/skills/{skill-name}/. If the target is missing, create it; only if it is already an oh-story skill (SKILL.md'smetadata.openclaw.sourcepoints to this repository, or contains the exact marker<!-- oh-story-managed: skill/{skill-name} -->) may it be backed up and then replaced. An existing sentinel cannot substitute for ownership evidence of an individual Skill; without evidence, retain and report.status=same's Skill only verifies, does not copy into itself. - Deploy one by one for the 18 canonical names
references/trae/commands/{name}.md; if any template is missing, stop as an incomplete deployment package, and do not generate fallback commands for the project's extra Skills. Only replace files with the same management marker. - According to "Deploy TRAE Agents" and the "TRAE / WorkBuddy fixed Agent roster", deploy the exact union of the general 8 names and the TRAE data 5 names (13 files) to
.trae/agents/. Only Agent built-in Agents can invoke sub-Agents; when the skill process encounters an unavailable sub-Agent, it must use the definedsolo/directfallback。 - Write
references/trae/rules/*.mdto.trae/rules/, only replacing files with the<!-- oh-story-managed: rule/... -->marker; TRAE rule frontmatter usesalwaysApply: falseandglobs, and does not copy Claudepathsfrontmatter. Writereferences/trae/AGENTS.md.tmplaccording to the "AGENTS.md merge strategy" into the rootAGENTS.md, only replacing the block between<!-- BEGIN oh-story-managed: trae -->and<!-- END oh-story-managed: trae -->, preserving the user's other paragraphs. - Write
references/trae/hooks/story_trae_hook.jsandstory_hook_core.jsto.trae/hooks/; the runner only replaces files of the same name whose header comment proves them to be the oh-story TRAE adapter. For an existing shared core, it must first runtrae-core-ownership.py --candidate <文件> --registry references/trae/legacy-managed-sha256.json, or prove byte-identity with a trusted sibling core in the same project; exit 3 (unmanaged)/2 (registry error) are both retained and reported, not overwritten. After replacement, runnode --checkand the cross-adapter byte-parity check, then merge according to the "TRAE hooks.json merge algorithm".trae/hooks.json; it is forbidden to overwrite the user configuration wholesale with a template. Windows nativeRunCommandis provided by PowerShell, and the runner must simultaneously cover the tested staticSet-Content、Add-Content、Out-File、Copy-Item、Move-Item、New-Itemdisk-write forms; dynamic expressions, splatting,.NETAPI, and unrecognized external programs are still covered by the Skill self-check and post-write backstop, and it must not claim that all PowerShell writes can be hard-blocked in PreToolUse. - Verify that the managed name sets of
.trae/skills/and.trae/commands/are both exactly equal to canonical 18, that the managed Agent name set is exactly equal to the TRAE 13-name union listed in the "TRAE / WorkBuddy fixed Agent roster", that the rule/hooks/AGENTS markers are complete, and that the hooks contract tests pass. The user's other.traeassets must still be present. .story-deployed'starget_cliwritestraeor a multi-target combination,references_dirwrites.trae/skills/story-setup/references/agent-references. The installation report lists the backup directory, conflicts/no-op, the 18 Skill / 18 Command / 13 Agent verification results, and Agent availability, and prompts the user to open a new TRAE session to refresh Skills / Commands / Rules / Subagents / Hooks.
WorkBuddy settings.json merge algorithm (when target_cli includes workbuddy)
- First determine whether this session has actually enabled the oh-story plugin: only accept that the currently executing Skill path is located under the CodeBuddy plugin installation root, that the runtime registry explicitly returns
oh-story, or that an availablecodebuddy plugin listexplicitly shows the plugin as enabled. A manifest in the repository, a disabled copy on disk, or the user saying verbally "I installed it" cannot substitute for runtime evidence. - When the plugin is enabled, choose
references/workbuddy/hooks/disabled-hooks.json; for project-local mode, choosereferences/workbuddy/hooks/project-hooks.json. Detectpython3/python/pyaccording to cross-platform rules, and callmerge-workbuddy-settings.py --existing {项目}/.codebuddy/settings.json --template <所选模板> --output {项目}/.codebuddy/settings.json; if there is no Python, stop the WorkBuddy branch and do not hand-write JSON. - The helper only includes in the command
story_workbuddy_hook.jsis registered as an oh-story managed item: first remove it from all historical events/matchers, then append it according to the selected template. User hooks, permissions, models, MCP, and unknown top-level fields are all preserved; repeated execution must be byte-idempotent. - project-local mode writes
story_workbuddy_hook.jsandstory_hook_core.jsinto.codebuddy/hooks/, and confirms that each of the four current registrations occurs exactly once. plugin mode no longer registers a second set of project Hooks,.codebuddy/settings.jsonoh-story runner registrations must be zero. "Both copies produce identical output" must not be used to prove compatibility. - Validate that Hook output uses only CodeBuddy-supported fields: all JSON output branches have top-level
continue: true; PreToolUse denial useshookSpecificOutput.permissionDecision=deny; commit reminders use top-levelsystemMessage; healthy no-op stdout is empty. matchers declare only tools already covered by the runner's target-resolution fixtures.
WorkBuddy / CodeBuddy Code native deployment algorithm (when target_cli contains workbuddy)
WorkBuddy Desktop embeds the CodeBuddy Code CLI; project mode natively discovers .codebuddy/skills/、.codebuddy/commands/、.codebuddy/agents/、.codebuddy/rules/ and .codebuddy/settings.json. It must not be downgraded to generic skills-only.
- Per the "canonical Chinese main package Skill list", copy the 18 Skills to
.codebuddy/skills/{skill-name}/; replace only main package directories whose ownership can be proven by this repository's metadata or exact markers, and preserve the user's other Skills. When source and target are the same, record no-op. - For each of the 18 canonical Skills, copy
references/workbuddy/commands/{name}.mdto.codebuddy/commands/{name}.md; if a template is missing, stop as the package is incomplete, and do not generate fallback commands for project extensions. Here these are project bare commands/story-*; the plugin manifest does not load this batch of Commands. - Per "Deploy WorkBuddy Agents" and the "TRAE / WorkBuddy fixed Agent roster", deploy the exact union (10 cards) of the 8 generic names and the 2 WorkBuddy data physical names to
.codebuddy/agents/; project cards use bare agent names, invoked by theAgenttool'ssubagent_typefield. The four read-only logical data-analysis roles call the pooled runner by mapping, and the logical cards are not copied to the registry. The plugin-only nameoh-story:<name>may be used only when the current registry actually returns it. - Merge
references/workbuddy/rules/*.mdinto.codebuddy/rules/, replacing only files with the same management marker; then handle the currently single effective memory file per the "WorkBuddy memory merge strategy". It is forbidden to use a very short CODEBUDDY file to obscure an existingAGENTS.md。 - Per the "WorkBuddy settings.json merge algorithm", choose the mutually exclusive project-local or plugin branch, and run the Node syntax, shared core byte-parity, Chinese body pre-write/post-write gates, and merge idempotency fixtures. On Windows, if PowerShell is used, only static write commands already covered by dedicated fixtures are hard gates; dynamic expressions, splatting, .NET APIs, or unrecognized external disk-writing programs must still rely on Skill self-checks and post-write fallbacks, and the installation report must not claim that "all PowerShell writes can be hard-intercepted".
- Validate that
.codebuddy/skills/and.codebuddy/commands/'s managed name set is exactly equal to canonical 18, the managed Agent name set is exactly equal to the union of the WorkBuddy 10 names listed in the "TRAE / WorkBuddy fixed Agent roster", the rule/memory markers are unique, and the user's other.codebuddyassets are still present. Validate that the pooled runner's four logical role mappings are complete, unique, and point to real cards within the Skill; if the WorkBuddy embedded or standalonecodebuddycan be found on this machine, also run at the repository rootcodebuddy plugin validate .Verify the plugin manifest; when a command is unavailable, explicitly record it as not executed, and do not falsely claim it passed. .story-deployed'starget_cliwriteworkbuddyor multi-target combination,references_dirwrite.codebuddy/skills/story-setup/references/agent-references. The installation report separately lists: project command/story-*;plugin-only Skill/oh-story:story-*; the Hook's current sole registration source; Agent registry results; PowerShell hard-gate boundaries. After deployment, fully executereferences/workbuddy/runtime-activation.md, open a new WorkBuddy / CodeBuddy session to refresh discovery results; when not actually confirmed in/skills、/agents、/hooks, only static/synthetic runtime pass may be reported.
Plugin installation does not go through the project copy algorithm: repository root .codebuddy-plugin/plugin.json is the only canonical manifest, all paths start with ./ , exposing only Skills, Agents, Hooks, and not Commands with the same names. Plugin hooks and project hooks must be mutually exclusive; even if project story-setup deployment of Skills/Commands/Agents/Rules is subsequently run, plugin hooks remain the sole registration source, and disabled-hooks.json is used to clear old project registrations.
Managed asset convergence and endpoint reduction (required for TRAE / WorkBuddy)
- Phase 1, before modifying
target_cli, simultaneously saveprevious_targetsanddesired_targets. First complete deployment of the new endpoint and retirement of the removed endpoint; only after all verification passes may the sentinel be atomically written back; do not modify.story-deployedfirst and leave old assets that would still be discovered by the platform. - When the target endpoint is still retained, name-set convergence must also be done: Skill / Command use canonical 18 as the sole roster, TRAE Agent uses the common 8 names listed in "TRAE / WorkBuddy fixed Agent roster" + the 5 TRAE data names (13 total) as the sole roster, and WorkBuddy Agent uses the common 8 names listed in the same section + the 2 physical WorkBuddy data names (10 total) as the sole roster. List as stale managed assets any Skill / Command / Agent / Rule that has an existing exact management marker/repository metadata but is no longer in the corresponding exact name set. Back up first, then delete only these stale items whose attribution can be proven; items with the same name but no marker are never deleted. After deletion, remove an empty directory only when the directory is truly empty.
- When removing
previous_targetsfromtrae:- For the
.trae/managed assets about to be changed, create.trae/.oh-story-backups/<UTC时间戳>/full relative-path backup; - use
merge-trae-hooks.py --template references/trae/hooks/disabled-hooks.jsonto remove from.trae/hooks.jsonand remove onlystory_trae_hook.jsregistration, preserve user hooks/top-level fields, and rerun to confirm byte idempotence; - delete only the
.trae/skills、commands、agents、rulesmanaged items and the two management hook scripts that can be proven by this section's attribution gate; fromAGENTS.mdremove only the TRAE BEGIN/END management block.
- For the
- When removing
previous_targetsfromworkbuddy:- First back up the project management assets about to be changed to
.codebuddy/.oh-story-backups/<UTC时间戳>/; - Use
merge-workbuddy-settings.py --template references/workbuddy/hooks/disabled-hooks.jsonto remove from.codebuddy/settings.jsonthe project oh-story Hook registration, leave user settings and hooks untouched, and rerun to confirm byte idempotence; - delete only
.codebuddy/skills、commands、agents、rulesmanaged items and project hook scripts with exact attribution evidence; from the current sole memory file remove only the WorkBuddy BEGIN/END block. If that memory file was created by story-setup and only whitespace remains after removal, it may be deleted after backup; otherwise keep it. - Project endpoint reduction does not equal uninstalling user-level/plugin-level oh-story; an enabled plugin is uninstalled only separately via the CodeBuddy plugin management command.
- First back up the project management assets about to be changed to
- The two project runners must also check the sentinel at every event entry: if a valid
target_cliexists and does not contain the current end, immediately return success with empty stdout. This is the defense line for mid-way failures and cannot replace the aforementioned physical registration/discovery asset cleanup. - Retirement acceptance must simultaneously prove: managed Hook registrations are 0; managed Skill/Command/Agent/Rule/memory blocks are no longer discovered by the target platform; user asset bytes are unchanged; the backup can be rolled back; running again is a no-op. If any item fails, do not update the sentinel, and report the partial retirement path.
OpenClaw skills-only deployment algorithm (when target_cli contains openclaw)
OpenClaw Phase 1 deploys only skills, not OpenClaw agents/hooks/plugin.
- Read the fixed 18 Skill directories according to the "canonical Chinese main package Skill list".
- Write to the target project
skills/{skill-name}/, replacing only these 18 story-setup managed directories; retain the user's other directories underskills/, and do not inject them into the Chinese main package. - Each
SKILL.mdmust satisfy the OpenClaw frontmatter constraints:name/descriptionis a single-line key-value,metadatais a single-line JSON object and containsmetadata.openclaw。 - Copy
skills/story-setup/references/openclaw/AGENTS.md.tmplto the projectAGENTS.md, and merge according to the "AGENTS.md merge strategy". .story-deployed'starget_cliwrite toopenclawor a multi-end combination;references_dirfor OpenClaw writeskills/story-setup/references/agent-references。- Installation report prompt items are in Phase 3 Step 12.
Reasonix skills-only deployment algorithm (when target_cli contains reasonix)
Reasonix (DeepSeek-Reasonix CLI) currently deploys only skills and AGENTS.md, not Reasonix hooks/custom agents (the hook I/O contract and sub-agent behavior lack a verifiable real CLI, left for a later phase).
- Copy the fixed 18 Skills to the target project according to the "canonical Chinese main package Skill list"
skills/{skill-name}/; replace only these known directories managed by story-setup, and retain the user's other directories. - Create at the project root
.agents/skills → ../skillsa relative symlink (the skill root shared with Codex), so that when Reasonix natively scans.agents/skillsit discovers these skills; if it is already a symlink pointing toskills/keep it, and if it is occupied as a normal directory do not overwrite it and prompt in the installation report. When symlinks are not enabled on Windows, skip this step and instead go through the rootreasonix-plugin.json'sreasonix plugin install。 - Copy
skills/story-setup/references/reasonix/AGENTS.md.tmplto the projectAGENTS.md, and merge according to the "AGENTS.md merge strategy". - Verify
skills/story-setup/references/agent-references/has been copied into place along with the completestory-setupskill. If the current execution source is the same path within the project, the safety precheck returnssame, and this step must be a no-op; copying the directory into itself again is prohibited. .story-deployed'starget_cliwrite toreasonixor a multi-end combination;references_dirfor Reasonix writeskills/story-setup/references/agent-references。- Installation report prompt items are in Phase 3 Step 14.
Generic Web AI / other Agent deployment algorithm (when target_cli contains generic)
The generic path targets environments that can read project files, such as NarraFork, Web AI, and custom Agents, and deploys only generic files, without declaring platform-native hooks/agents capabilities.
- Copy the fixed 18 Skills to the target project according to the "canonical Chinese main package Skill list"
skills/{skill-name}/; replace only these known directories managed by story-setup, and retain the user's other directories. - Copy
skills/story-setup/references/generic/AGENTS.md.tmplto the projectAGENTS.md, and merge according to the "AGENTS.md merge strategy". - Verify that
skills/story-setup/references/agent-references/has been copied into place along with the completestory-setupskill. If the current execution source is the same path within the project, the safety precheck returnssame, and this step must be a no-op; it is forbidden to copy the directory into itself again. .story-deployed'starget_cliwritegenericor a multi-target combination;references_dirfor generic, writeskills/story-setup/references/agent-references。- See Phase 3 Step 13 for installation report reminder items.
Step 8: Create deployment marker
- Create the
.story-deployedfile (sentinel file) - Write the following fields (YAML
key: valueformat, read by the hook usingreferences/templates/hooks/lib/sentinel.sh):deployed_at: <date -u +"%Y-%m-%dT%H:%M:%SZ"> agents_version: 39 setup_skill_version: 1.2.22 target_cli: claude-code(或 opencode、codex、zcode、trae、workbuddy、openclaw、reasonix、generic,或其任意组合) resolver_strategy: project-local-skill-reference references_dir: .claude/skills/story-setup/references/agent-references(Codex 写 .codex/skills/...;ZCode 写 .zcode/skills/...;TRAE 写 .trae/skills/...;WorkBuddy 写 .codebuddy/skills/...;OpenClaw / Reasonix / generic 写 skills/...;多端用逗号分隔) - This file is used by session-start.sh and the writing skills to detect deployment status and avoid repeated reminders
- When target_cli includes claude-code, also create a one-time marker file
.claude/.agents-pending-restart(an empty file is sufficient). At the start of the next session, session-start.sh uses it to confirm that agents have been registered with the new session and automatically deletes the marker—used to confirm to the user that "the restart has taken effect." ZCode does not create this marker because it does not deploy project agents. - If
.story-deployedalready exists butagents_versionis missing, non-integer, or less than39, update hooks/agents/rules/reference bundle according to this flow (seeUPGRADING.mdfor specific changes); if it is greater than39, execution has already stopped in Phase 1 and must not be overwritten with a downgrade
Phase 3: Verify installation
- Verify hooks registration:
- Check whether the hooks field in
.claude/settings.local.jsonis correct - Check whether the scripts under
.claude/hooks/exist and have execute permission - Check whether
.claude/hooks/lib/common.shand.claude/hooks/lib/sentinel.shexist
- Check whether the hooks field in
- Verify rules paths:
- Check whether the rule files under
.claude/rules/exist and containpathsfrontmatter
- Check whether the rule files under
- Verify agents:
- Check whether the 8 agent definition files under
.claude/agents/exist
- Check whether the 8 agent definition files under
- Verify agent reference bundle:
- Check that the reference files under
.claude/skills/story-setup/references/agent-references/are complete - Check that all
story-setup/references/agent-references/<file>.mdcan resolve to the deployed bundle
- Check that the reference files under
- Verify deployment marker:
- Check whether
.story-deployedexists and contains a timestamp,agents_version: 39、setup_skill_version: 1.2.22、target_cli、resolver_strategy、references_dir
- Check whether
- Output installation report:
- List all deployed files
- List items that need attention (such as existing configurations that have been merged)
- ⚠️ Restart reminder (must be output prominently): this deployment wrote
.claude/agents/, but these custom agents are only registered by Claude Code assubagent_type。Please start a new Claude Code session before you begin writing, otherwise in the current session, when story-review / story-long-write etc. try to spawnstory-architect、narrative-writeretc., they will get "subagent_type unavailable" and fall back to solo (single perspective, losing multi-agent collaboration). To determine whether it has taken effect: run/story-reviewin a new session. If the report header isEffective Mode: full/lean, registration succeeded; if it isFallback: ... -> soloNote that it is still in an old session or not registered. - It can be used after restart
/story-long-writeor/story-short-write - If "Configure OpenCode Agent Model" was executed, output the Agent model configuration summary:
Agent 模型配置: story-architect → <高端模型>(provider/model-id) narrative-writer → <中端模型>(provider/model-id) character-designer → <中端模型>(provider/model-id) story-researcher → <中端模型>(provider/model-id) revision-governor → <中端模型>(provider/model-id) chapter-extractor → <低端模型>(provider/model-id) consistency-checker → <低端模型>(provider/model-id) story-explorer → <低端模型>(provider/model-id) - If automatic detection fails (
opencode modelsunavailable), output the manual configuration guide:无法自动检测模型列表。以下 Agent 未配置模型,将使用主模型,成本可能较高: - chapter-extractor(建议使用低成本模型) - consistency-checker(建议使用低成本模型) - story-explorer(建议使用低成本模型) 手动配置方法:编辑 .opencode/agents/{agent名}.md,在 frontmatter 中添加: model: provider/model-id 可用模型列表与成本可通过 opencode models --verbose 查看(输出含每模型 cost/context)。 模型库与定价见 OpenCode 官方模型源 https://models.dev/。
- Verify the opencode deployment (only when target_cli contains opencode):
- Check whether
.opencode/agents/the 8 agent definition files under exist, and whether the frontmatter containsmode: subagentandpermissionfields - Check whether
.opencode/plugins/story-hooks.tsexists - Check whether
.opencode/plugins/lib/story_hook_core.jsexists andnode --checkpasses (story-hooks.ts imports it, the shared body-writing guard core byte-identical to the.zcodecopy; placed in thelib/subdirectory to avoid OpenCode single-level.opencode/plugins/*.jsplugin auto-discovery) - Check whether
.opencode/commands/the command name set under matches the current OpenCode template manifest - Check whether
skills/story-setup/references/agent-references/the reference files under are complete and the count matches the source directory - Check whether
opencode.jsonthepluginarray contains the story-hooks entry - Check whether
.git/hooks/pre-commitexists and has execute permission (skip the execute permission check on Windows) - Check whether
.opencode/agents/the agent file frontmatter under can be parsed by YAML, andmodel:(if configured) is a valid top-level scalar, rather than merely grepping themodel:substring
- Check whether
- Verify the Codex deployment (only when target_cli contains codex):
- Check whether
AGENTS.mdcontains the Codex story skill routing sections - Check whether
.codex/agents/the 8.tomlagent definition files under exist and can be parsed - Check whether
.codex/hooks.jsonexists and the JSON is valid, Unixcommandonly started viarun-story-hook.sh, WindowscommandWindowsonly started viarun-story-hook.cmd, there is no registration that directly callsstory_codex_hook.pyregistration of - Check whether
.codex/hooks/story_codex_hook.py、run-story-hook.sh、run-story-hook.cmdexists, the Python syntax is valid, and the POSIX/Windows launcher can locate the project root from a nested cwd - Check whether
.codex/skills/story-setup/references/agent-references/the reference files under are complete and the count matches the source directory - The installation report must indicate: Codex requires trusting the project
.codex/configuration layer, and at/hooksreview/trust non-managed hooks; after deployment, open a new Codex session for the custom agents to take effect; if the current runtime still returnsunknown agent_type, degrade to solo/direct according to each skill's fallback rules
- Check whether
- Verify the ZCode deployment (only when target_cli contains zcode):
- Check whether the root
AGENTS.mdcontains the ZCode$story-*routing, outline guard, and solo/direct fallback - Check according to the "canonical Chinese main package Skill manifest" whether
.zcode/skills/and.zcode/commands/are exactly 18 names, and verify that the frontmatter and naming are consistent - Check whether
.zcode/hooks/story_zcode_hook.js、.zcode/hooks/story_hook_core.jsexists andnode --checkpasses - Check
.zcode/config.jsonJSON is valid, and validate according to the hooks mutual-exclusion branch in Step 4 of the "ZCode Deployment Algorithm": when the oh-story plugin is not installed,hooks.enabled=true, register only ZCode-supported events, and allprocessargs point to the project Hook; when the oh-story plugin is installed (.zcode-plugin/plugin.jsonhas globally registered this batch of hooks), instead validate that.zcode/config.jsondoes not contain (or has removed) this batch of oh-story hooks registrations——must notmerge theconfig.json.patchhooks block back in just to make validation pass, otherwise the same event will be triggered twice - Check
.zcode/skills/story-setup/references/agent-references/is complete and all reference paths are resolvable - Use fixtures to invoke SessionStart, PreToolUse deny/allow, and PostToolUse, confirming that stdout is empty when there are no findings, and that output conforms to ZCode strict JSON when there is output
- The installation report must note: ZCode 3.3.4 does not execute project/plugin custom agents, and full/lean multi-Agent requests will reliably degrade to solo/direct; Hooks depend on
nodein PATH; after deployment, open a new ZCode session to refresh Skills/Commands/AGENTS.md
- Check whether the root
- Verify TRAE Code deployment (only when target_cli contains trae):
- Check that root
AGENTS.mdhas only one completeoh-story-managed: traemanagement block, and the user's other sections are still present - Check that the managed name sets of
.trae/skills/and.trae/commands/are both exactly equal to canonical 18; each skill hasSKILL.md, and each command hasname/descriptionandoh-story-managedmarkers - Check that the managed name set of
.trae/agents/is exactly equal to the 8 generic names + 5 TRAE data names (13 total) listed in the "TRAE / WorkBuddy Fixed Agent Roster", frontmatter is parseable,nameis unique, there are no Claude-only fields, and management markers are complete - Check that the management files of
.trae/rules/containalwaysApply/globs, and do not contain Claudepathsfrontmatter - Check that
.trae/hooks/story_trae_hook.js、story_hook_core.jsexists andnode --checkpasses;.trae/hooks.jsonisversion: 1, uses only TRAE-supported events and the{type,command,timeout}hook schema, matcher coversRunCommand|Write|Edit, andSubagentStop - Use fixtures to invoke SessionStart, PreToolUse deny/allow, and PostToolUse, confirming that stdout is empty when there are no findings, and that output conforms to TRAE
hookSpecificOutput; rerunmerge-trae-hooks.pyto confirm user hooks/unknown fields are preserved and byte-idempotent - Check that the oh-story command in
.claude/settings*.jsonremains a directbash ...(must not embed a POSIX-only parseableif); all Claude entrypoints sourceTRAE_PROJECT_DIRwhich containslib/common.shsilent-exit logic. Use the same PreToolUse fixture to prove that the Claude-imported Hook produces no output under TRAE, and the TRAE native Hook executes only once - The installation report must list
.trae/.oh-story-backups/the backup location for this run and any conflicts/no-ops, and note: review/enable this project's Hooks on the Hooks page in TRAE Settings, and confirm the projectAGENTS.md/ Rules import enabled, then open a new TRAE session to refresh native Skills / Commands / Rules / Subagents / Hooks; if Subagents Beta is unavailable, full/lean multi-Agent requests must reportFallback: TRAE subagent unavailable -> solo/direct
- Check that root
- Verify WorkBuddy / CodeBuddy Code deployment (only when target_cli contains workbuddy):
- Check whether the managed name sets of
.codebuddy/skills/and.codebuddy/commands/are exactly equal to canonical 18; each command has valid frontmatter and management markers - Check whether the managed name set of
.codebuddy/agents/is exactly equal to the general 8 names listed in the "TRAE / WorkBuddy fixed Agent roster" + WorkBuddy data physical 2 names (10 cards total), with a total of no more than 19, unique names, and frontmatter using only CodeBuddy-supported fields; each logical role of the pooled runner must map uniquely to a real card within a Skill. In a new session, actually invoke the base Agent,story-data-fetcherand one logical role of the pooled runner separately; only after success may you report that multi-Agent mode is in effect; the settings page "enable all" cannot replace Task registry evidence - Check the management block of
.codebuddy/rules/and the uniquely effective memory file; the project's originalAGENTS.mdcontent must still be read directly or imported via@AGENTS.md/@../AGENTS.md, and template conditional placeholders must not remain; when both root and.codebuddy/two CODEBUDDY files exist, a conflict must be reported rather than guessing the priority - Check whether
.codebuddy/settings.jsonpreserves user fields, and verify by mutually exclusive branches: in project-local mode the current 4 oh-story Hook registrations each appear exactly once, with events onlySessionStart/PreToolUse/PostToolUse; in plugin mode project registrations are zero. Running the helper twice must be byte-idempotent - Use fixtures to invoke SessionStart (including agents_version 38/39/40), PreToolUse deny/allow/commit, and PostToolUse; confirm that healthy no-op stdout is empty and all output has
continue: true, that deny and reminder fields conform to the CodeBuddy schema, and that path escapes cannot bypass the project root - Check that the plugin manifest does not contain a
commandsfield with the same name as Skills, and that all custom paths start with./; if available, run realcodebuddy plugin validate .. The installation report clearly states the project/story-*and plugin/oh-story:story-*differences, the sole Hook source, the PowerShell hard-gate boundary, and prompts to open a new session
- Check whether the managed name sets of
- Verify OpenClaw deployment (only when target_cli contains openclaw):
- Check whether
AGENTS.mdcontains OpenClaw story skill routing sections - According to the "canonical Chinese main package Skill list", check the fixed 18 target Skills under
skills/, and that eachSKILL.mdcontains a single-linename, a single-linedescription, and single-line JSONmetadata.openclaw - Check whether the reference files under
skills/story-setup/references/agent-references/are complete and the count matches the source directory - The installation report must state: OpenClaw Phase 1 is skills-only; OpenClaw agents/hooks are not deployed, runtime hard interception is unavailable, and the outline guard before writing body text, commit reminders, and session/compact automatic injection serve only as soft constraints within skills; OpenClaw snapshots eligible skills at session startup, so after deployment, if commands/skills do not appear, a new OpenClaw session must be opened or you must wait for the skills watcher to refresh
- Check whether
- Verify generic Web AI / other Agent deployment (only when target_cli contains generic):
- Check
AGENTS.mdcontains generic story skill routing sections - According to the "canonical Chinese main package Skill list", check
skills/for the fixed 18 target Skills, and eachSKILL.mdis readable - Check
skills/story-setup/references/agent-references/for complete reference files with a count matching the source directory - The installation report must state: generic does not deploy platform-specific hooks/custom agents; hard blocks such as outline guard, commit reminders, session/compact injection, and multi-agent collaboration are all executed as soft constraints within the skill or via solo/direct fallback
- Check
- Verify Reasonix deployment (only when target_cli includes reasonix):
- Check
AGENTS.mdcontains Reasonix story skill routing sections and solo/direct fallback instructions - According to the "canonical Chinese main package Skill list", check
skills/for the fixed 18 target Skills, and eachSKILL.mdis readable - Check that project
.agents/skillsis a symlink pointing toskills/(POSIX; enables Reasonix native scanning to discover skills); when the symlink is not created on Windows, instead confirm that the rootreasonix-plugin.jsoncan be used forreasonix plugin install - Check
skills/story-setup/references/agent-references/for complete reference files with a count matching the source directory - The installation report must state: Reasonix is currently skills-only; Reasonix hooks/custom agents are not deployed, so before writing the main text the outline guard, commit reminders, and session/compact auto-injection only exist as soft constraints within the skill, and Skills involving specialized Agents use solo/direct fallback; you can use
reasonix doctor capabilitiesto verify skill discovery, and after deployment if the new skills are not displayed, open a new Reasonix session or use the rootreasonix-plugin.jsonnative plugin installation
- Check
Template placeholder
| Placeholder | Replacement rule | Example |
|---|---|---|
{项目名} |
User project name or directory name | "Sword Comes", "Hidden Guard" |
{书名} |
Book title directory name (consistent with the directory) | Same as {项目名} , or user-defined |
{目标平台} |
Target publishing platform | Qidian, Fanqie, Jinjiang, Zhihu Yanyan |
{作者名} |
User pen name or nickname | When unspecified, use "Author" |
Remove the curly braces when replacing. If the user does not specify a project name, use the current directory name. Unspecified placeholders are left as-is and not replaced.
CLAUDE.md merge strategy
When the user already has a CLAUDE.md, merge by marker/section:
- Prefer to identify the story-setup managed block marker (if an old project already has the marker, only replace the content inside the marker)
- When there is no marker, read the user's existing CLAUDE.md and split it into a section map by
##heading - Read the template CLAUDE.md.tmpl and split it in the same way
- Standard sections in the template (Skill routing table, file structure, collaboration rules, restore context after Compact)overwritethe user's section with the same name
- Sections unique to the user (custom content)retainleave unchanged
- For unknown conflicts, use AskUserQuestion to let the user choose which version to keep
AGENTS.md merge strategy (OpenCode / Codex / ZCode / TRAE Code / OpenClaw / Reasonix / generic)
When the user already has AGENTS.md, merge by marker/section:
- Prioritize identifying the story-setup management block marker (if the old project already has the marker, only replace the content inside the marker)
- When there is no marker, read the user's existing AGENTS.md and split it by
##headings into a section map - OpenCode uses
skills/story-setup/references/opencode/AGENTS.md.tmpl; Codex usesskills/story-setup/references/codex/AGENTS.md.tmpl; ZCode usesskills/story-setup/references/zcode/AGENTS.md.tmpl; TRAE Code usesskills/story-setup/references/trae/AGENTS.md.tmpl(only replace theoh-story-managed: traemarker block); OpenClaw usesskills/story-setup/references/openclaw/AGENTS.md.tmpl; Reasonix usesskills/story-setup/references/reasonix/AGENTS.md.tmpl; general-purpose Web AI / other Agents useskills/story-setup/references/generic/AGENTS.md.tmpl - the template's standard sections (Skill routing table, file structure, collaboration rules, context recovery after Compact) override sections with the same name; user-unique sections are preserved
- When deploying to multiple platforms simultaneously, keep only one copy of the common paragraphs usable by Codex/OpenCode/ZCode/TRAE/OpenClaw/Reasonix/generic; distinguish tool-specific notes with subsections or platform management markers to avoid overwriting each other
WorkBuddy memory merge strategy
CodeBuddy treats the root CODEBUDDY.md and .codebuddy/CODEBUDDY.md as project memory, and only falls back to reading AGENTS.mdwhen there is no CODEBUDDY memory. Therefore, a short template must not be unconditionally created to shadow existing common conventions.
- Also check the root
CODEBUDDY.md、.codebuddy/CODEBUDDY.mdand the rootAGENTS.md. If both CODEBUDDY copies exist, stop memory writing and report the conflict, asking the user to choose a single canonical location; do not guess the loading priority, and do not delete either copy. Other WorkBuddy assets may continue to be verified, but the installation report must be marked as memory not closed-loop. - When only one CODEBUDDY copy exists, marker-merge the WorkBuddy management block in place; if
AGENTS.mdalso exists, replace the template placeholder{{OH_STORY_AGENTS_IMPORT}}according to the target location with the root file's@AGENTS.mdor the.codebuddyfile's@../AGENTS.md, ensuring the original common conventions still enter the context. When there is no AGENTS, replace with a blank line. - When neither CODEBUDDY copy exists but
AGENTS.mdalready exists, directly merge the WorkBuddy management block into the existingAGENTS.md, and replace the import placeholder with blank; do not create a new CODEBUDDY file, thereby continuing to use CodeBuddy's AGENTS fallback. - When none of the three exists, create
.codebuddy/CODEBUDDY.md, replacing the import placeholder with blank. All branches only replace the text insideBEGIN/END oh-story-managed: workbuddy, preserving user-unique content. - Post-write verification: exactly one management block;
{{OH_STORY_AGENTS_IMPORT}}must not remain; when an existing AGENTS is present and CODEBUDDY is ultimately used, the correct relative import must be present; merging again is byte-idempotent.
Redeploy
.story-deployeddoes not exist → fresh install, execute all of Phase 2.story-deployedexists andagents_version: 39→ prompt that it is already deployed, AskUserQuestion to confirm whether to redeploy; state in the prompt that redeployment only uses the current local skill package to refresh project files, while formal updates to the skill itself go through the fixed GitHub Release asset:npx skills add https://github.com/qin1473692580-ux/oh-story-claudecode/releases/latest/download/oh-story-release.zip -y -g.story-deployedexists butagents_versionis missing, not an integer, or less than39→ prompt that an update is needed, re-execute Phase 2 to refresh the agents/hooks/rules/reference bundle managed by story-setup; CLAUDE.md / AGENTS.md / CODEBUDDY.md / settings.local.json / .codex/hooks.json / .zcode/config.json / .trae/hooks.json / .codebuddy/settings.json follow the merge strategy; back up TRAE managed assets first; re-evaluate WorkBuddy hooks for plugin/project mutual exclusion.story-deployedexists andagents_versionis greater than39→ current skill version is too old, stop and prompt to update oh-story-claudecode first; do not overwrite the project's updated deployment
Reference Materials
| File | Purpose |
|---|---|
| references/templates/hooks/ | 8 hook script templates + story_hook_core.js(shared implementation for main-text network/word count/outline guard/continuity/commit detection, the same copy as OpenCode/ZCode) + story_hook_cli.js(node bridge for bash hook to call the core) + lib/common.sh/lib/sentinel.sh(check-prose-after-write.sh handles the PostToolUse fallback for Write/Edit; Bash redirection,tee、touch、cp、mv、install main-text writing is best-effort recognized by the shared PreToolUse core and executes the outline/tracking gate; unrecognized Bash writes are still covered by the Codex Stop end-of-turn git scan) |
| references/templates/rules/ | 4 path-scoped rule templates |
| references/templates/agents/ | 8 agent definition templates (story-architect, character-designer, narrative-writer, consistency-checker, revision-governor, story-researcher, story-explorer, chapter-extractor) |
| references/agent-references/ | Reference material copies included with Agent templates; deploy to .claude/skills/story-setup/references/agent-references/to avoid cross-skill references |
| references/templates/settings-hooks.json | hooks registration JSON fragment |
| references/templates/inspection progress.md.tmpl | Per-chapter Phase 5 QC sub-item completion status table, mechanically checkable |
| references/codex/AGENTS.md.tmpl | Codex project root AGENTS.md template |
| references/codex/agents/ | 8 Codex custom agent TOML templates |
| references/codex/hooks/hooks.json | Codex hooks registration JSON template (deploy to .codex/hooks.json) |
| references/codex/hooks/story_codex_hook.py | Codex hook adapter (deploy to .codex/hooks/story_codex_hook.py) |
| references/openclaw/AGENTS.md.tmpl | OpenClaw project root AGENTS.md template (skills-only) |
| references/generic/AGENTS.md.tmpl | Generic Web AI / other Agent project root AGENTS.md template (skills + soft checks) |
| references/zcode/ | ZCode AGENTS, Commands, workspace config patch and strict JSON Hook runner |
| references/trae/ | TRAE Code native AGENTS, Commands, Agents, Rules and Hooks adapter |
| scripts/merge-trae-hooks.py | Merge by stable command identity .trae/hooks.json, preserving user configuration |
| scripts/trae-core-ownership.py + references/trae/legacy-managed-sha256.json | Before overwriting the TRAE shared core, classify ownership precisely by marker / old-version SHA; fail closed on unknown files |
| references/workbuddy/ | WorkBuddy / CodeBuddy Code native memory templates, project Commands, Agents, Rules and Hooks adapter; plugin-mode Skills/Agents/Hooks also reuse these verified artifacts |
| scripts/merge-workbuddy-settings.py | Merge or remove project Hooks in .codebuddy/settings.json by stable runner identity, preserving user configuration and ensuring plugin/project mutual exclusivity |
Repository root .codebuddy-plugin/plugin.json |
CodeBuddy plugin specification manifest; expose only Skills, Agents, Hooks to avoid conflicts with same-named Commands |
Repository root scripts/generate-workbuddy-adapter.py |
During maintenance, deterministically generate WorkBuddy artifacts from the reviewed TRAE roles/commands and shared core; not delivered with project deployment |
Process Handoff
Pipeline: Deploy Location: initialization (frontmost)
| Timing | Jump to | Command |
|---|---|---|
| Deployment complete, start writing | story-long-write / story-short-write | /story-long-write or /story-short-write |
| Import an existing novel for breakdown | story-import | /story-import |
| Requires browser login state (ranking scan/breakdown text retrieval) | browser-cdp | /browser-cdp; generic requires the platform to allow local scripts/browser control |
Invocation syntax per platform: Claude /名、Codex/ZCode $名、TRAE Code /名, WorkBuddy project mode /名, WorkBuddy plugin-only mode /oh-story:名、OpenClaw /skill 名, Reasonix / generic directly naming the skill.