# okstra-schedule-gen AI Manual

## Source

- Skill source: [`skills/okstra-schedule-gen/SKILL.md`](../../../skills/okstra-schedule-gen/SKILL.md)
- Schedule template: [`templates/reports/schedule.template.md`](../../../templates/reports/schedule.template.md)
- Schedule validator: [`validators/validate-schedule.py`](../../../validators/validate-schedule.py)
- Stage Map read side: [`scripts/okstra_project/state.py`](../../../scripts/okstra_project/state.py)
- Selection semantics: [`scripts/okstra_ctl/schedule_semantics.py`](../../../scripts/okstra_ctl/schedule_semantics.py)
- Work-category source of truth: [`scripts/okstra_ctl/work_categories.py`](../../../scripts/okstra_ctl/work_categories.py)
- workStatus inference reference: [`skills/okstra-inspect/SKILL.md`](../../../skills/okstra-inspect/SKILL.md)

## Purpose and invocation

`okstra-schedule-gen` gathers non-done tasks in a task group and produces one client-facing work schedule from user-selected unfinished implementation stages.

Public invocation:

```text
/okstra-schedule-gen [task-group]
```

This is a host skill, not a schedule-generation shell command. Use `stage-map` and `validate-schedule.py` only as backend contracts inside the skill.

Output location:

```text
<PROJECT_ROOT>/.okstra/tasks/<task-group-segment>/schedule/<task-group-segment>-plan-<YYYY-MM-DD_HH-MM-SS>.md
```

Do not use it for single-task status analysis or phase execution. Use `okstra-inspect status` and `okstra-run` for those jobs.

## Preflight and task-group resolution

Run one literal-token preflight call:

```bash
okstra preflight --runtime claude-code
```

On `Okstra preflight: failed`, show `Reason` and `Recovery`, then stop. On
`Okstra preflight: ready`, carry the fixed `Project root` line. Resolve an
explicit task-group from the invocation or host request. If none is unambiguous,
run `okstra model-io task-selection-input --project-root <projectRoot>` and ask
the user to choose from the fixed `Task` rows; never guess. Then run
`okstra model-io schedule-input --project-root <projectRoot> --task-group <group>`
and use only its fixed task metadata rows.

On zero matches, report that the task group was not found and do not create a file.

## Candidate filter

`workStatus` is used only to decide which tasks are candidates. When it is missing or empty, use the `okstra-inspect` `status.4` inference table.

- Exclude resolved `done` tasks.
- Include every other resolved state.
- If no task remains, report that all tasks are done and do not create a file.

Do not render `workStatus` as the detailed task status. The per-task `Status` value is `<taskType> / <currentPhase>`.

## Source-aware Stage Map resolution

For every candidate task, call:

```bash
okstra stage-map <task-key> --text
```

The successful fixed response carries `Status`, `Task key`, `Task root`, `State`,
`Source plan path`, and lossless numbered `Stages`, `Done stages`, and `Planning`
count/name/value rows.

Handle each result explicitly:

- `Status: ready`, `State: ready`: use exactly `Source plan path`; do not pick a report by mtime or `latestReportRecordPath`. Select only stages not present in the done-stage rows.
- `Status: ready`, `State: missing`: record an empty source and empty stage sets, mark the task `[NEEDS-PLANNING]`, and emit no forward Work Breakdown, Gantt, or day total for it.
- `Status: error` or another state: stop before drafting and report `Failure stage` and `Failure reason`. A corrupt or conflicting source must never fall back to a guessed report.

A valid selected set is dependency-closed: every transitive prerequisite of a selected stage is either also selected or present in `doneStages`. Completed prerequisites remain evidence only and are never scheduled forward.

If a ready task has no unfinished stages, render `_Complete — no remaining stage_` and omit forward effort.

## Stage selection

Offer up to three dependency-closed cumulative bundles in topological order, plus all remaining stages. A custom set is accepted only after closing it over unfinished prerequisites; completed prerequisites are preserved separately.

Skip the picker when the remaining work has only one possible bundle and use all unfinished stages. Record the final stage numbers as `selectedStages`.

## Temporary selection contract

Write a paired draft and selection input with one timestamp:

```text
.okstra/tasks/<task-group-segment>/schedule/.draft/<timestamp>.md
.okstra/tasks/<task-group-segment>/schedule/.draft/<timestamp>.selection.json
```

The selection file is a temporary verification input. It freezes the exact source, full stage map, completed stages, and user-selected forward work so both validators judge the same facts instead of re-resolving mutable task state.

Schema version 1:

```json
{
  "schemaVersion": 1,
  "tasks": [
    {
      "taskKey": "demo:group:DEV-1",
      "taskId": "DEV-1",
      "state": "ready",
      "sourcePlanPath": "/absolute/path/final-report-implementation-planning-001.data.json",
      "selectedStages": [2, 3],
      "doneStages": [1],
      "stages": [
        {
          "stageNumber": 1,
          "title": "Prepare port",
          "dependsOn": [],
          "stepCount": 2
        },
        {
          "stageNumber": 2,
          "title": "Build adapter",
          "dependsOn": [1],
          "stepCount": 3
        },
        {
          "stageNumber": 3,
          "title": "Wire consumer",
          "dependsOn": [2],
          "stepCount": 2
        }
      ]
    }
  ]
}
```

Include every candidate task. A `missing` task has an empty `sourcePlanPath`, `selectedStages`, `doneStages`, and `stages`. Convert the CLI stage-row keys to the camel-case selection boundary exactly as shown.

## Phase classification

Only these canonical categories are valid:

| workCategory | Default phase |
|---|---|
| `bugfix` | Phase 1 for High or Med-High risk; otherwise Phase 2 |
| `feature` | Phase 2 |
| `improvement` | Phase 2 |
| `refactor` | Phase 3 |
| `ops` | Phase 3 |

Priority overrides category: P0 maps to Phase 1, P1/P2 to Phase 2, and P3 to Phase 3. An unknown or missing raw category falls back to Phase 2 with a one-line rationale naming the raw value. Do not invent another category.

## Template contract

Follow `schedule.template.md` exactly. The required top-level order is:

1. `## At a Glance`
2. `## Executive Summary`
3. `## Task Dependency Graph`
4. optional `## Gantt Chart`
5. `## Phase 1: Critical Fixes`
6. `## Phase 2: Enhancements`
7. `## Phase 3: Architecture`
8. `## Execution Priority Matrix`
9. `## Cross-Task Dependencies & Shared Concerns`
10. `## Risk Mitigation Strategy`
11. `## Recommended Immediate Actions`
12. optional final `## Glossary`

Keep an empty required section and render `_none_`. Headings and field labels stay as English template literals; body prose is Korean.

Each scheduled task uses this stage-level Work Breakdown shape:

```markdown
| Stage | Title | Steps | Depends On | Days |
|---:|---|---:|---|---:|
| 2 | Build adapter | 3 | 1 (done) | 2.0 ~ 3.0 |
| 3 | Wire consumer | 2 | 2 | 1.0 ~ 2.0 |
```

Use the template's Effort Sizing Criteria values without redefining them. Allocate a task's range across selected stages in `stepCount` proportion: round every stage except the last to 0.5 day and let the last absorb the remainder. The stage ranges must sum to the task range, and finite task ranges must sum to the displayed total. XXL, missing, and complete tasks contribute no forward total.

An unrepresentable half-day allocation is a validation error. Do not substitute a fallback allocation algorithm; revise the task sizing or selected-stage scope.

## Gantt contract

Render a plain fenced relative-day Gantt when the selected stages have finite day ranges. Every forward row is identified by stage and repeats its Work Breakdown range:

```text
DEV-1 Stage 2  ████      days=2.0~3.0
DEV-1 Stage 3      ████  days=1.0~2.0
```

A row is labelled `Stage <n>` when exactly one task is scheduled and `<TASK-ID> Stage <n>` when more than one is; the annotation is `days=<lower>~<upper>`. Spell the stage out — `S1` is an opaque code that costs the reader a lookup and saves five characters. Do not emit a row for a completed, unselected, missing, or unknown stage. Bar length is arithmetic: one column is half a day, so a bar runs `lower / 0.5` filled cells `█` then `(upper - lower) / 0.5` open cells `░`.

Skip the chart only when no forward task has a finite day signal, and state the concrete reason. Do not use calendar dates, Mermaid, PlantUML, Graphviz, or another graph language.

A host-supplied directive or the first `## Directive` in the configured analysis material may override the render/skip heuristic, but it cannot override stage selection, dependency closure, or validated day arithmetic.

## Client-facing boundary

Assume the team has the required authority. Exclude approval waits, permission checks, stakeholder coordination, decision checklists, and internal blocker codes from forward engineering work. Gantt duration and totals represent engineering work only.

Resolve opaque source-report codes inline or in the optional final Glossary. Decision-item codes do not belong in the schedule.

## Two validation gates

Run both gates against the same draft and temporary selection contract.

1. Deterministic gate:

   ```bash
   python3 ~/.okstra/lib/validators/validate-schedule.py <draft> --selection-json <selection>
   ```

2. Only after that command passes, create a new `.okstra/agent-invocations/schedule-verification/<invocation-id>.instructions.md` with the draft, selection JSON, and checks, but not the lead's reasoning. Run `okstra agent-prompt materialize --purpose schedule-verification --audience schedule-verifier ...` and verify the returned metadata before dispatch. A native host call uses the verified prompt body plus `hostModelValue`; a deterministic provider process uses `okstra worker-dispatch`, the prompt path, and `modelExecutionValue`. The verifier checks narrative coherence, phase rationale, executable order, engineering-only scope, and contradictions with the structured rows.

Capture the raw verifier return under the purpose directory's `.tmp/`, then run `okstra agent-prompt materialize-result`, `complete`, and `verify-completion` in order. Parse only the verified `returnedBody`; an inline or unverified response cannot pass the narrative gate.

If either gate finds a defect, revise the same draft in place and restart from the deterministic gate. Allow at most two revision rounds across both gates. Never publish a draft that has not passed both gates in that order.

After both gates pass:

1. Move the same draft content to the collision-safe final path; do not re-render it.
2. Re-read it and run the installed format validator on the final path, falling back to the repository validator only when needed.
3. Delete the temporary selection file only after final validation passes.
4. Report completion in Korean with the output path, included/excluded counts, finite total range, and lead-plus-verifier mode.

## Forbidden patterns

- Guessing a planning report after `stage-map` reports a structured error.
- Treating `workStatus` as the detailed schedule status.
- Scheduling completed or non-selected stages.
- Publishing a Gantt row without its `Stage <n>` label and `days=` range, or abbreviating that label to `S<n>`.
- Drawing stage order in `## Task Dependency Graph` — that graph carries cross-task edges only; stage order lives in the Work Breakdown's `Depends On` column.
- Dispatching narrative validation before deterministic `--selection-json` validation.
- Re-rendering after validation instead of promoting the same draft.
- Deleting the selection contract before final validation.
- Publishing after more than two unsuccessful revision rounds.
