一键导入
autospec-compose-normalize
Use when Autospec runtime provisioning detects Docker Compose files that require migration for isolated worktree environments.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Use when Autospec runtime provisioning detects Docker Compose files that require migration for isolated worktree environments.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Use when the user wants to plan a feature — bootstrap repo if missing, brainstorm a design spec, decompose into linked GitHub issues, or split an existing spec into issues. Stops after Phase 3 and hands off to /autospec-run for autonomous implementation.
Use when the user has already run /autospec-define (or otherwise has a populated set of auto-implement GitHub issues) and wants the implementation half — Phases 4-6 — to run autonomously with admin auto-merge. Supports --profile <name> filtering against ~/.autospec/model-profiles.yml.
Use when the user wants /autospec-autonomous to run the autospec machinery unattended for weeks — a perpetual self-driving conductor that walks a never-idle priority waterfall (Tier 0 control channel + Tier 1 backlog→main + Tier 1.5 open-issue promotion + Tier 2 local discovery + Tier 3 architecture/coverage improvement + Tier 4 internet/operator discovery + capability-gated Tiers 5-7 growth outbound/define/measure), parks before quota exhaustion, obeys a GitHub control channel for live steering, and resumes automatically.
Use when the user wants to revalidate a running app against a spec, regenerate missing or weak tests, audit UI controls/forms/validation/dropdowns/API behavior/accessibility, or prove implemented features actually work after autospec-run.
Observe a live autospec-autonomous conductor read-only by summarizing typed status, timeline, launch, heartbeat, tier, and discovery artifact surfaces.
Use when the user wants to ship a feature end-to-end across multiple commits — bootstraps repo if missing, brainstorms a design spec, decomposes into linked GitHub issues, or splits an existing spec into issues, then runs an autonomous implementation loop with auto-merge.
| name | autospec-compose-normalize |
| description | Use when Autospec runtime provisioning detects Docker Compose files that require migration for isolated worktree environments. |
Orchestrate one fingerprinted prerequisite migration. Delegate every YAML decision and
edit to the Rust normalize-compose command; never implement Compose policy in the
prompt, shell, or model.
| Capability | Contract |
|---|---|
| Shell | Run direct argument vectors and preserve command exit status. |
| GitHub | Use gh for issue, pull-request, review, CI, and merge operations. |
| Worktrees | Use worktree-guard.sh; never mutate the primary checkout. |
| Claims | Use claim-guard.sh in strict, all-or-nothing mode. |
| Subagent dispatch policy | Follow the AGENTS.md subagent-vs-inline decision matrix. |
origin/main, then retry runtime provisioning.autospec runtime env up command.
Do not acquire claims, create a worktree, apply edits, or claim isolation.The caller determines the mode from its own workflow context. Do not invent an environment variable to infer it.
Run the check unconditionally from the current Git worktree, even when neither runtime manifest exists yet:
PLAN_FILE=$(mktemp "${TMPDIR:-/tmp}/autospec-compose-plan.XXXXXX")
ERROR_FILE="${PLAN_FILE}.err"
if ! autospec runtime env normalize-compose --repo "$PWD" --check >"$PLAN_FILE" 2>"$ERROR_FILE"; then
if grep -q 'NORMALIZE_COMPOSE_NOT_FOUND' "$ERROR_FILE"; then
rm -f "$PLAN_FILE" "$ERROR_FILE"
exit 0
fi
sed -n '1,120p' "$ERROR_FILE" >&2
rm -f "$PLAN_FILE" "$ERROR_FILE"
exit 1
fi
Read the versioned JSON deterministically. Require schema_version to equal 1,
fingerprint to be exactly 64 lowercase hexadecimal characters, and
remaining_diagnostics to be empty. A non-empty diagnostic list is terminal and must
be printed verbatim; do not create a migration. Treat malformed JSON and unknown schema
versions as terminal. Treat NORMALIZE_STALE_SOURCE from any later command as terminal
and restart from a fresh check.
Use Python's standard JSON parser rather than line parsing or an external JSON tool:
FINGERPRINT=$(python3 - "$PLAN_FILE" <<'PY'
import json, re, sys
plan = json.load(open(sys.argv[1], encoding="utf-8"))
fingerprint = plan.get("fingerprint", "")
if plan.get("schema_version") != 1:
raise SystemExit("unsupported normalization schema_version")
if plan.get("remaining_diagnostics"):
raise SystemExit(json.dumps(plan["remaining_diagnostics"], indent=2))
if not re.fullmatch(r"[0-9a-f]{64}", fingerprint):
raise SystemExit("fingerprint must be 64 lowercase hexadecimal characters")
print(fingerprint)
PY
)
If edits is empty, delete the temporary files and return success. Otherwise continue
with the exact marker <!-- autospec-compose-fingerprint: SHA256 -->, replacing
SHA256 with $FINGERPRINT in every issue and pull-request body.
Search issue bodies and pull-request bodies in the current repository for the exact fingerprint marker. Inspect complete JSON results so a substring or title match cannot select another migration.
MARKER="<!-- autospec-compose-fingerprint: $FINGERPRINT -->"
WORKFLOW_GUARD="${AUTOSPEC_SCRIPTS_DIR:-$HOME/.autospec/scripts}/autospec-compose-normalize-guard.sh"
LOOKUP_RESULTS=$("$WORKFLOW_GUARD" lookup "$FINGERPRINT")
The guard searches the exact 64-character fingerprint in each body, then filters for the full marker. Its bounded result set therefore cannot be displaced by hundreds of unrelated generic Compose migrations.
gh issue reopen <number> and reuse it. For a closed,
unmerged pull request, run gh pr reopen <number> and reuse it when GitHub permits.
If reopening the pull request fails, print its URL as a terminal recovery blocker;
never create a replacement issue or pull request for that fingerprint.origin/main into the
active feature worktree, then rerun the check before env up.For every direct unmanaged invocation, run "$WORKFLOW_GUARD" direct-refuse "$FINGERPRINT" and return on its expected exit status 3. This command prints all
matching URLs (or the explicit no-match state) and never invokes runtime provisioning.
This is the exactly one migration issue, branch, worktree, and pull request invariant for a fingerprint.
Consume only the Rust plan's repo-relative input_paths and manifest_path. Include
the selected manifest even when it does not exist yet, so its creation is leased. Do
not rediscover inputs with Git, filesystem globs, or YAML parsing.
CLAIM_FILE="${PLAN_FILE}.claims"
python3 - "$PLAN_FILE" "$CLAIM_FILE" <<'PY'
import json, pathlib, sys
plan = json.load(open(sys.argv[1], encoding="utf-8"))
inputs = plan.get("input_paths")
manifest = plan.get("manifest_path")
if not isinstance(inputs, list) or not all(isinstance(p, str) for p in inputs):
raise SystemExit("normalization plan input_paths must be a string array")
if not isinstance(manifest, str) or not manifest:
raise SystemExit("normalization plan manifest_path must be a non-empty string")
paths = sorted(set([manifest, *inputs]))
for value in paths:
path = pathlib.PurePosixPath(value)
if path.is_absolute() or ".." in path.parts or "\n" in value or "\t" in value:
raise SystemExit(f"normalization claim path is not repo-relative: {value!r}")
with open(sys.argv[2], "w", encoding="utf-8") as output:
output.write("\n".join(paths) + "\n")
PY
SELECTED_MANIFEST=$(python3 - "$PLAN_FILE" <<'PY'
import json, sys
print(json.load(open(sys.argv[1], encoding="utf-8"))["manifest_path"])
PY
)
CLAIM_INPUTS=$(sed '/^$/d' "$CLAIM_FILE")
OLD_IFS=$IFS
IFS='
'
set -- $CLAIM_INPUTS
IFS=$OLD_IFS
CLAIMS_HELD=0
COMPOSE_CLAIM_SESSION="${AUTOSPEC_SESSION_ID:-}"
if [ -z "$COMPOSE_CLAIM_SESSION" ]; then
COMPOSE_CLAIM_SESSION=$("$WORKFLOW_GUARD" new-session-token)
fi
release_compose_claims() {
if [ "${CLAIMS_HELD:-0}" = 1 ]; then
"$WORKFLOW_GUARD" claim release "$COMPOSE_CLAIM_SESSION" "$@"
CLAIMS_HELD=0
fi
}
trap 'release_compose_claims "$@"' EXIT HUP INT TERM
"$WORKFLOW_GUARD" claim acquire "$COMPOSE_CLAIM_SESSION" "$@"
CLAIMS_HELD=1
"$WORKFLOW_GUARD" claim verify "$COMPOSE_CLAIM_SESSION" "$@"
The acquire is all-or-nothing. On conflict, release nothing, print the owning session,
and retry lookup later. The status verification turns claim-guard's deliberately
fail-open unwritable-store mode into a fail-closed migration prerequisite. Hold and
refresh the claims through merge. Call
release_compose_claims "$@" on success and rely on the trap on every terminal path.
After claims succeed, repeat the exact fingerprint lookup. This closes the race between lookup and acquire. If a match appeared, release and reuse it.
LOOKUP_RESULTS_AFTER_CLAIM=$("$WORKFLOW_GUARD" lookup "$FINGERPRINT")
Create one issue with label needs-classify; do not add auto-implement directly. Its
body must include the fingerprint marker and these lintable sections:
## Goal: one concrete sentence naming the selected manifest and Compose migration.## Acceptance criteria: checkbox lines with paths, commands, or numeric results.## Implementation outline: every claimed file that the migration may touch.## Tests required: real Compose validation and the repository full suite.### Primary smoke test (inner loop): one command line only.Run ${AUTOSPEC_SCRIPTS_DIR:-$HOME/.autospec/scripts}/lint-issue.sh on the body
before gh issue create. Then run
autospec-classify for the new issue and verify needs-classify was replaced by
auto-implement with both ctx:* and reasoning:* labels before implementation.
bash "${AUTOSPEC_SCRIPTS_DIR:-$HOME/.autospec/scripts}/lint-issue.sh" "$ISSUE_BODY"
ISSUE_URL=$(gh issue create --title "feat: migrate Compose isolation $FINGERPRINT" \
--body-file "$ISSUE_BODY" --label needs-classify)
ISSUE_NUMBER=${ISSUE_URL##*/}
Invoke the installed classifier through the current harness, substituting the concrete number (never dispatch a symbolic command):
/autospec-classify --issues <ISSUE_NUMBER>
Use branch feat/compose-isolation-$FINGERPRINT truncated only after enough digest
characters remain unique. Create it from current origin/main in one linked worktree:
bash "${AUTOSPEC_SCRIPTS_DIR:-$HOME/.autospec/scripts}/worktree-guard.sh" create \
--branch "feat/compose-isolation-${FINGERPRINT}" \
--path "/tmp/wt-compose-isolation-${FINGERPRINT}"
Exactly one worktree owns implementation. Never apply in the caller's feature worktree.
Inside the migration worktree, rerun --check and require the fingerprint to equal the
claimed value. Then delegate the only writes to Rust:
autospec runtime env normalize-compose --repo "$PWD" --apply --fingerprint "$FINGERPRINT"
autospec runtime env normalize-compose --repo "$PWD" --check
The second check must have no edits or remaining diagnostics. It also proves the Rust
normalizer can resolve docker compose --profile "*" --all-resources ... config --format json. Run the repository full suite, commit the changed Compose/manifest files, and
push the single branch. Open one pull request containing the same fingerprint marker,
the issue-closing reference, exact verification evidence, and scoped file list.
PR_URL=$(gh pr create --title "feat: migrate Compose isolation $FINGERPRINT" \
--body-file "$PR_BODY" --base main \
--head "feat/compose-isolation-${FINGERPRINT}")
Run normal CI and review gates: gh pr checks, the repository implementation linter,
and a fresh reviewer that must return LGTM. Fix findings on new commits and repeat.
At every existing CI/heartbeat poll, refresh the same lease without starting another
background loop:
"$WORKFLOW_GUARD" claim refresh "$COMPOSE_CLAIM_SESSION" "$@"
Merge only after required CI and review pass, using the repository's authorized
gh pr merge mode. Do not release claims merely because the pull request opened.
After merge is confirmed, release claims, remove the migration worktree, fetch
origin/main, merge it into the caller's feature worktree, rerun this skill's check,
and only then continue to autospec runtime env up.
| Signal | Action |
|---|---|
NORMALIZE_COMPOSE_NOT_FOUND | Return success; no migration is needed. |
| Remaining diagnostics | Print them and stop; no model-authored YAML workaround. |
| Stale fingerprint/source | Discard the plan and restart from --check. |
| Existing fingerprint marker | Reuse the issue/PR; never create a sibling migration. |
| Claim conflict | Wait and repeat lookup; never weaken strict mode. |
| Failed CI or non-LGTM review | Keep the claim, fix normally, and rerun the gates. |