一键导入
ks-writing-plan
// Use this when direction is already clear and the next job is to compress it into an executable block with scope, done criteria, and routing.
// Use this when direction is already clear and the next job is to compress it into an executable block with scope, done criteria, and routing.
Lightweight task compressor. Turn messy input into a one-page brief that can route to roundtable or writing-plan without replacing direction decisions.
Formal quality gate with multi-persona review, confidence thresholds, and QA routing based on fresh verification evidence.
Direction convergence skill. Use brainstorm, align, or challenge mode to turn messy questions or existing proposals into a clear directional decision.
Fast failure classifier. Decide whether the problem is a spec gap, an implementation bug, or a rollback candidate before routing to writing-plan, diagnose, or ship.
Use this when the system is broken, tests are failing, or behavior is abnormal and the root cause is still unknown. No investigation, no fix.
Use this when the current block is already clear and the job is to complete it. Default route comes from test-first; only controlled low-risk exceptions may enter directly.
| name | ks-writing-plan |
| description | Use this when direction is already clear and the next job is to compress it into an executable block with scope, done criteria, and routing. |
| layer | decision |
| owner | writing-plan |
| inputs | ["direction_decision","roundtable_report"] |
| outputs | ["plan_document","current_block","plan_type"] |
| entry_modes | ["from-scratch","aligned-offline","plan-ready"] |
Preamble: see templates/preamble.md
Turns a direction decision into one executable block with scope, stop lines, entry conditions, and the next workflow step. Enter when direction is clear but the concrete current block, scope boundary, and done criteria still need writing. Does not make direction decisions, write implementation code, or substitute for technical design inside implement. If direction is still unclear, go to roundtable.
A task list is not a writing-plan output. If you find yourself writing "1. do A, 2. do B, 3. do C", stop and compress it into one executable block.
Skipping test-first must be justified in the plan document, not decided ad hoc during implementation.
Done criteria must be observable and testable. "clean code" is not a done criterion. "all new checks have executable verification" is.
| Type | Use when |
|---|---|
full-plan | new feature, broad scope, needs full expansion from goal to execution |
delta-plan | main approach already decided, only the difference, risks, and dependencies need filling in |
execution-card | small current block with clear scope and done criteria, only needs a sharp local definition |
roundtable or explicit user direction)Ask one question before proceeding:
Is there any technical decision in this direction that still changes scope or routing?
If yes, decide it before continuing. Do not pretend it is not there.
If the task closely matches a previous solution, check docs/solutions/ first and avoid re-planning something that already failed or already works.
| Condition | Recommended type |
|---|---|
| New feature, broad scope, needs full expansion | full-plan |
| Main approach decided, only delta matters | delta-plan |
| Small block with clear scope and done criteria | execution-card |
If unsure, default to full-plan. It is the most explicit option and the safest choice when the boundaries are unclear.
Core principle: produce one current block, not a task list.
If the plan still contains three parallel branches, the direction is not converged enough. Go back to roundtable.
current_block must:
Apply the scope test for each candidate item:
If I do not do this, can the current block still count as complete?
Concrete examples of scope test application:
| Candidate item | Test question | Result |
|---|---|---|
| "Add error handling to the new endpoint" | If missing, is the block complete? No, errors would be unhandled. | Include |
| "Refactor the related utility module" | If missing, is the block complete? Yes, utility refactor is separate. | Exclude |
| "Update the API documentation" | If missing, is the block complete? No, docs are part of the contract. | Include |
| "Migrate the entire database schema" | If missing, is the block complete? Yes, migration is a separate block. | Exclude |
Done criteria must be observable and testable. Strengthen weak wording:
| Weak | Better |
|---|---|
| "code quality should be good" | "new logic has executable checks and all targeted checks pass" |
| "performance should improve" | "P95 latency drops from 500ms to 100ms" |
| "security should be better" | "OWASP self-check finds no high-risk issue in the touched path" |
| "tests should pass" | "all checks in test_contract pass with zero failures" |
| "the feature should work" | "the new endpoint returns 200 for valid input and 422 for invalid input" |
| "edge cases handled" | "empty input, max-length input, and null input each produce the documented error response" |
| Risk | Default shape |
|---|---|
low | copy edits, config-only changes, internal script fixes with no behavior change |
medium | ordinary feature changes, interface changes, delta implementation on existing approach |
high | user-path changes, behavior changes, data changes, release work, incidents |
Rules:
lowlowhigh risk blocks must pass through test-first without exceptionqa_required = true when user paths, browser interactions, critical integrations, or high runtime risk are involvedqa_required = false for internal scripts, low-risk non-interactive fixes, or similar changestrueDefault: next_skill = test-first.
Direct implement is only valid when ALL of these are true:
risk_level = lowtest-first is safetest-first is written inside the plan documentCircuit breaker: if the same block is revised 3 times during planning, stop. Escalate to roundtable because the direction is not converged enough to plan.
# Plan: [block name]
## Plan Type
[full-plan / delta-plan / execution-card]
## Direction Source
[roundtable output or explicit user direction]
## Current Block
[one sentence describing the current executable block]
## Scope
### Included
- [files, modules, or behaviors inside this block]
### Excluded (Scope Boundaries)
- [explicit non-goals]
## Done Criteria
[observable, testable completion standards — one per item, no vague wording]
## Entry Conditions
[what must already be true before this block starts]
## Risk Level
- **risk_level**: [low / medium / high]
- **Why**: [1-2 sentences justifying this level]
## TDD Routing
- **Default next skill**: [test-first / implement]
- **If direct implement is allowed, why**: [only for low-risk controlled exceptions; must be explicit]
## QA Expectation
- **qa_required**: [true / false]
- **Why**: [user path, browser interaction, runtime integration, or not]
## Technical Decisions
- [decision 1]: [what was chosen and why]
## Dependencies
- [external conditions or modules this block depends on]
## Next Step
**next_skill**: [default test-first; implement only for controlled low-risk exceptions]
Save to docs/keystone/plans/YYYYMMDD-[slug].md.
| Failure | Action |
|---|---|
| Direction not actually clear | Route back to roundtable |
| Scope cannot be bounded | Ask the scope test question; if still unclear, route to roundtable |
| Done criteria untestable | See E1 |
| Risk level disagreement | See E2 |
| Plan type unclear | See E3 |
| 3 revisions to same block | Circuit breaker: route to roundtable |
When a done criterion cannot be made observable:
roundtable to resolve the ambiguityescalate = true with reason "untestable done criteria"roundtable.When the user insists on a lower risk level than the evidence supports:
test-first incorrectlyWhen no plan type cleanly fits:
full-plan (the most explicit option)execution-carddelta-plan when the delta boundary is unclear; it requires knowing what the base plan isdecision: block-defined confidence: 0.9 rationale: The scope is compressed into one executable block, the done criteria are observable, and the next routing step matches the risk level. fallback: If implementation exposes a broken boundary, return to writing-plan and redefine the block. escalate: false next_skill: default test-first; implement only for low-risk controlled exceptions next_action: Enter test-first to lock the behavior boundary unless the plan explicitly authorizes the low-risk implement exception.
mkdir -p docs/keystone/plans
_BLOCK_TITLE="${BLOCK_TITLE:?set BLOCK_TITLE to current block title}"
_PLAN_TYPE="${PLAN_TYPE:?set PLAN_TYPE to full-plan|delta-plan|execution-card}"
_RISK_LEVEL="${RISK_LEVEL:?set RISK_LEVEL to low|medium|high}"
_NEXT_SKILL="${NEXT_SKILL:?set NEXT_SKILL to test-first|implement}"
_QA_REQUIRED="${QA_REQUIRED:?set QA_REQUIRED to true|false}"
_PLAN_SLUG=$(printf '%s' "$_BLOCK_TITLE" | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | tr -d '.,!?')
_PLAN_PATH="docs/keystone/plans/$(date +%Y%m%d)-$_PLAN_SLUG.md"
_KS_CLI="${KEYSTONE_CLI:-./keystone}"
[ -f "$_PLAN_PATH" ] || { echo "plan_document not found: $_PLAN_PATH"; exit 1; }
$_KS_CLI state set current_stage "writing-plan" >/dev/null
$_KS_CLI state set current_block "$_BLOCK_TITLE" >/dev/null
$_KS_CLI state set last_decision "block-defined" >/dev/null
$_KS_CLI state set risk_level "$_RISK_LEVEL" >/dev/null
$_KS_CLI state set qa_required "$_QA_REQUIRED" >/dev/null
$_KS_CLI state set artifacts.plan_document "$_PLAN_PATH" >/dev/null
$_KS_CLI state set artifacts.plan_type "$_PLAN_TYPE" >/dev/null
$_KS_CLI state set artifacts.next_skill_hint "$_NEXT_SKILL" >/dev/null
case "$_NEXT_SKILL" in
implement)
if [ "$_RISK_LEVEL" != "low" ]; then
echo "invalid next_skill=$_NEXT_SKILL for risk_level=$_RISK_LEVEL"
exit 1
fi
_EXIT_CODE="ok"
_EXIT_NEXT="implement"
_EXIT_REASON="Controlled low-risk exception: go directly to implementation"
;;
test-first)
_EXIT_CODE="ok"
_EXIT_NEXT="test-first"
_EXIT_REASON="The plan requires behavior locking before implementation"
;;
*)
echo "invalid next_skill=$_NEXT_SKILL"
exit 1
;;
esac
$_KS_CLI state set exit_code "$_EXIT_CODE" >/dev/null
$_KS_CLI state set exit_reason "$_EXIT_REASON" >/dev/null
$_KS_CLI state set next_skill "$_EXIT_NEXT" >/dev/null
echo "{\"skill\":\"writing-plan\",\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"decision\":\"block-defined\",\"confidence\":0.85,\"risk_level\":\"$_RISK_LEVEL\",\"block_name\":\"$_BLOCK_TITLE\"}" >> .keystone/telemetry/events/$(date +%Y-%m).jsonl