AgentSkillsCN

os-tk-plan

制定简洁明了的项目计划(新建项目)或重构/更新计划(既有项目)。适用于在 OpenSpec 提案或 epic 规划之前,进行全局性的战略部署与统筹规划。

SKILL.md
--- frontmatter
name: os-tk-plan
description: Create a concise project plan (greenfield) or refactor/update plan (brownfield). Use for big-picture planning before OpenSpec proposals/epics.

/os-tk-plan

Inputs

  • Request text (from $ARGUMENTS)
  • Optional --mode greenfield|brownfield
  • Optional --interview to run interview mode first
  • Optional --no-interview to explicitly skip interview mode
  • Optional --max-questions N to limit interview questions
  • Optional --needs-review to mark this plan as requiring review
  • Optional --plan-id <id> to associate a plan id for review tracking

Determine mode

  • If --mode provided, use it.
  • Else: if repo has real code/config (src/, app/, lib/, package.json, pyproject.toml, go.mod, Cargo.toml, etc.), treat as brownfield. Otherwise greenfield.

Interview mode (NEW)

If --interview is provided (or if enabled in config):

  1. Run os-tk-interviewer subagent to collect requirements
  2. Save interview output to INTERVIEW_OUTPUT
  3. Update request with interview context: REQUEST_WITH_CONTEXT="${REQUEST}\n\n## Interview Context\n${INTERVIEW_OUTPUT}"
  4. Pass REQUEST_WITH_CONTEXT to planner chain
  5. Note that interview was run in dev notes (if enabled)

If --no-interview is provided:

  • Skip interview mode, use original request directly
  • Set REQUEST_WITH_CONTEXT="$REQUEST" (no interview context)

If neither flag provided:

  • Check config for default interview setting (optional future enhancement)
  • Default to no interview (backward compatible)
  • Set REQUEST_WITH_CONTEXT="$REQUEST" (no interview context)

Execution:

bash
# Parse flags
INTERVIEW_MODE=false
NO_INTERVIEW_MODE=false
NEEDS_REVIEW=false
PLAN_ID=""

while [[ $# -gt 0 ]]; do
  case "$1" in
    --interview)
      INTERVIEW_MODE=true
      shift
      ;;
    --no-interview)
      NO_INTERVIEW_MODE=true
      shift
      ;;
    --needs-review)
      NEEDS_REVIEW=true
      shift
      ;;
    --plan-id)
      PLAN_ID="$2"
      shift 2
      ;;
    *)
      REQUEST="$*"
      break
      ;;
  esac
done

# Auto-generate plan id when needs-review is set
if [[ "$NEEDS_REVIEW" == "true" ]] && [[ -z "$PLAN_ID" ]]; then
  PLAN_ID="plan-$(date +%Y%m%d-%H%M%S)"
  echo "Auto-generated plan id: $PLAN_ID"
fi

# If plan id is set, ensure it's persisted and shown to the user later
# (Plan ID will be added to final plan output and dev notes)

# Check if interview mode is active
if [[ "$INTERVIEW_MODE" == "true" ]] && [[ "$NO_INTERVIEW_MODE" != "true" ]]; then
  echo "=== Interview Mode ==="
  echo "Collecting requirements through questions..."
  echo ""

  # Run interviewer agent
  INTERVIEW_OUTPUT=$(subagent({
    "agent": "os-tk-interviewer",
    "task": "Conduct interview for request: $REQUEST"
  }))

  # Check if interview succeeded
  if [[ -z "$INTERVIEW_OUTPUT" ]]; then
    echo "ERROR: Interview failed to complete"
    exit 1
  fi

  # Save interview to dev notes (if enabled)
  CONFIG_FILE=".os-tk/config.json"
  if [[ -f "$CONFIG_FILE" ]]; then
    DEV_NOTES_ENABLED=$(jq -r '.devNotes.enabled // false' "$CONFIG_FILE" 2>/dev/null || echo "false")
  else
    DEV_NOTES_ENABLED="false"
  fi

  if [[ "$DEV_NOTES_ENABLED" == "true" ]]; then
    SUMMARY="<summary bullets from interview>" REQUEST="$REQUEST" bash pi/skills/os-tk-interview/scripts/save-interview.sh
  fi

  echo ""
  echo "=== Interview Complete ==="
  echo "Proceeding to planning with interview context..."
  echo ""

  # Update request with interview context
  REQUEST_WITH_CONTEXT="${REQUEST}\n\n## Interview Context\n${INTERVIEW_OUTPUT}"
else
  # No interview mode
  REQUEST_WITH_CONTEXT="$REQUEST"
fi

Parallel scouting + planning (single subagent chain)

Use pi-async-subagents tool subagent with a parallel-in-chain fan-out/fan-in.

Important:

  • The planner must NOT spawn any subagents.
  • This chain is sync (async: false) because it includes a parallel step.
js
subagent({
  "agentScope": "both",
  "async": false,
  "chain": [
    {
      "parallel": [
        {
          "agent": "os-tk-repo-scout",
          "task": "(If this is a greenfield repo / no relevant code, say so quickly.)\n\nFind existing patterns, conventions, related code paths, and test patterns relevant to: " + (REQUEST_WITH_CONTEXT || "{task}") + ""
        },
        {
          "agent": "os-tk-librarian",
          "task": "DOCS mode: Find official docs, breaking changes, and examples relevant to: " + (REQUEST_WITH_CONTEXT || "{task}") + ""
        }
      ],
      "concurrency": 2,
      "failFast": false
    },
    {
      "agent": "os-tk-planner",
      "task": "Create a concise plan.\n\nRequest: " + (REQUEST_WITH_CONTEXT || "{task}") + "\nMode: <greenfield|brownfield> (infer from repo if not provided)\n\nScout findings:\n{previous}\n\nOutput MUST follow this template:\n# Plan (mode: <greenfield|brownfield>)\n\nContext (brownfield only):\n- ...\n\nSteps:\n1. ...\n\nRisks/Unknowns/Deps:\n- risk: ...\n- unknown: ...\n- dep: ...\n\nValidation:\n- ...\n\nUnresolved questions:\n- ...\n\nRules: extreme concision, numbered steps, include validation commands."
    },
    {
      "agent": "os-tk-gap-analyst",
      "task": "Review the plan for gaps. Request: " + (REQUEST_WITH_CONTEXT || "{task}") + ". Plan:\n{previous}"
    },
    {
      "agent": "os-tk-planner",
      "output": "final-plan.md",
      "task": "Revise the plan to address the gap analysis below.\n\nRequest: " + (REQUEST_WITH_CONTEXT || "{task}") + "\n\nGap analysis:\n{previous}\n\nWrite the FINAL plan (same template as before). Also write it to the chain output file per instructions."
    }
  ]
})

Return final plan to the user

The chain tool returns a summary including the chain directory, e.g.:

  • 📁 Artifacts: /tmp/pi-chain-runs/<runId>

After the chain completes:

  1. Extract the chain dir from the tool output.
  2. Read ${CHAIN_DIR}/final-plan.md.
  3. If PLAN_ID is set, rename, annotate, and persist the plan file:
bash
# Rename file to plan-<id>.md
PLAN_PATH=$(bash "pi/skills/os-tk-plan/scripts/rename-plan-file.sh" \
  --plan-id "$PLAN_ID" \
  --plan-file "${CHAIN_DIR}/final-plan.md")

# Annotate plan file with Plan ID
bash "pi/skills/os-tk-plan/scripts/annotate-plan-id.sh" \
  --plan-id "$PLAN_ID" \
  --plan-file "$PLAN_PATH"

# Persist to .os-tk/plans/
PLAN_PATH=$(bash "pi/skills/os-tk-plan/scripts/persist-plan-file.sh" \
  --plan-file "$PLAN_PATH")
  1. Return contents (now including Plan ID: ...) as the /os-tk-plan output.

Dev notes (mandatory when enabled)

If .os-tk/config.json has devNotes.enabled=true:

  • Create .os-tk/dev-notes/plan-<YYYYMMDD-HHMMSS>.md containing:
    • Request
    • Final plan
    • Snippets (validated) (if any)
    • Open questions
    • Plan ID (if available)
  • Append a one-line entry to .os-tk/dev-notes/INDEX.md linking the plan note.

If PLAN_ID is set and dev notes file exists, annotate it:

bash
bash "pi/skills/os-tk-plan/scripts/annotate-plan-id.sh" \
  --plan-id "$PLAN_ID" \
  --plan-file "$PLAN_PATH" \
  --dev-notes "${DEV_NOTES_FILE}"

Plan storage:

  • Final plan file is persisted to .os-tk/plans/<plan-id>.md
  • /os-tk-proposal --plan-id <id> will load this file automatically

Mark plan as requiring review (NEW)

If --needs-review is provided:

  • --plan-id <id> is optional; if omitted, it auto-generates plan-YYYYMMDD-HHMMSS
  • Mark plan as pending review in .os-tk/plan-approvals.json
  • Run:
bash
bash "pi/skills/os-tk-plan/scripts/mark-plan-needs-review.sh" --plan-id "$PLAN_ID"

This sets:

  • status: pending
  • requestedBy and requestedAt

The proposal gate will block until plan is approved.

Stop condition

STOP after printing the final plan and (if enabled) writing dev-notes. Ask for answers to unresolved questions.

Prohibited

  • No product code changes.
  • No ticket creation.