Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .ytstack/DECISIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -797,3 +797,22 @@ Plus: ops-layer split during the same session (yopstack created as own public re
**How to apply:** Keep Codex tool mappings in codex/adapter.md. The Codex SessionStart entry passes these as optional host context to the shared hook. Without trusted hooks, read the adapter explicitly before following skills. The small runtime helper supplies the shared scripts' existing CLAUDE_* inputs and resolves the repository root; those compatibility names do not require a Claude executable. All three lifecycle events use the original hook scripts. Do not reintroduce generated copies or a second skill tree.

**Supersedes:** The earlier generated-package decision and per-skill Codex-link approach. The host-specific manifests, three-event Codex registration, hook trust, and repository-subdirectory fix remain.

---

## 2026-11-11: Status line progress is one optional `progress` block in STATE.md, read by a plugin script (M021, issue #31)

**Context:** A project built its own status line segment by scraping a totals row out of a prose table in `STATE.md`. That works for one table and breaks silently when the prose changes. Claude Code plugins cannot set the main `statusLine`, and no documented path lets a status line command find plugin files across versions.

**Options considered:**
- A) A new progress file per project.
- B) An optional `progress` block in the `STATE.md` frontmatter, with the slice plan checkboxes as fallback.
- C) Several named tracks, or a `done` / `open` pair instead of `done` / `total`.

**Chose:** B with exactly one track (`label`, `done`, `total`, optional `waiting_on`). `bin/ytstack-status` prints the segment; `yt_progress_parse` is the only parser and serves the script and the STATE lint (W7). Plan progress is read from the default branch when the checkout is on another branch, the task pointer from the checkout. The script is found by a glob over the plugin cache in the user's own status line script. SessionStart does not maintain a link.

**Reason:** `STATE.md` exists in every project, already has machine-read frontmatter and is already linted. One parser means the segment and the lint cannot disagree, so a malformed block shows nothing instead of a wrong number. One track covers the case that motivated the issue; a list of tracks can be added later without breaking readers of the single block. A hook-maintained link would break the read-only contract of SessionStart and force every suite that fires the hook to isolate HOME.

**How to apply:** New readers of the block call `yt_progress_parse`; do not add a second parser. Skills that advance STATE update the block (`summarize-task`, `quick-task`). The status script stays free of network calls and `gh`. C is open for a later milestone when a project needs it.

**Supersedes:** None.
43 changes: 43 additions & 0 deletions .ytstack/M021-CONTEXT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
milestone: M021
project: ytstack
created: 2026-11-11T10:25:52Z
size: M
---

# M021 -- Context

## Goal

Any status line script can append one compact ytstack segment that shows project progress and the current task of the directory it runs in, read from `.ytstack/STATE.md` without per-project scraping.

## Exit criteria

- With a `progress` block in the `STATE.md` frontmatter, `bin/ytstack-status` prints label, percentage and done/total; with `waiting_on` set it also prints that item, truncated.
- Without the block it prints the active slice's task count taken from the checkboxes in `M###-S##-PLAN.md`.
- Outside a ytstack project it prints nothing and exits non-zero.
- In a linked worktree the plan progress comes from the default branch and the task pointer from the worktree's own `STATE.md`.
- A malformed block prints nothing; `yt_state_lint` reports it (integers, `done <= total`, short label).
- `summarize-task` and `quick-task` keep the block current when they advance STATE.
- `docs/statusline.md` documents the block, the two-line integration and a stable script location that survives plugin updates; README and CHANGELOG point at it.
- `bash tests/run-all.sh` passes and `bin/ytstack-check` reports no new failures.

## Size

M -- 2 slices. See `M021-ROADMAP.md` for slice breakdown.

## Planning input

GitHub issue #31 and the user's instruction to implement it. Milestone number M021 because M020 (Kimi adapter, issue #30) is planned in the main checkout and not committed yet.

## Decisions locked in discuss phase

2026-11-11: Exactly one `progress` track with `label`, `done`, `total` and optional `waiting_on`, as the issue proposes. Several named tracks and a `done`/`open` pair (the issue's open questions) stay out until a project needs them; the single block can be extended to a list later without breaking readers.

2026-11-11: One parser for the block lives in `hooks/lib/git-ctx.sh` and serves both the status script and the STATE lint, so the two cannot disagree about what is malformed.

2026-11-11: No network and no `gh` in the status script. The default branch is read from local refs only.

## Open questions

(none)
40 changes: 40 additions & 0 deletions .ytstack/M021-ROADMAP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
milestone: M021
project: ytstack
size: M
created: 2026-11-11T10:25:52Z
status: done
total_slices: 2
completed_slices: 2
---

# M021 Roadmap

**Goal:** Any status line script can append one compact ytstack segment that shows project progress and the current task of the directory it runs in, read from `.ytstack/STATE.md` without per-project scraping.

**Exit criteria:**
- With a `progress` block in the `STATE.md` frontmatter, `bin/ytstack-status` prints label, percentage and done/total; with `waiting_on` set it also prints that item, truncated.
- Without the block it prints the active slice's task count taken from the checkboxes in `M###-S##-PLAN.md`.
- Outside a ytstack project it prints nothing and exits non-zero.
- In a linked worktree the plan progress comes from the default branch and the task pointer from the worktree's own `STATE.md`.
- A malformed block prints nothing; `yt_state_lint` reports it (integers, `done <= total`, short label).
- `summarize-task` and `quick-task` keep the block current when they advance STATE.
- `docs/statusline.md` documents the block, the two-line integration and a stable script location that survives plugin updates; README and CHANGELOG point at it.
- `bash tests/run-all.sh` passes and `bin/ytstack-check` reports no new failures.

## Slices

Slice detail lives in per-slice `M021-S##-PLAN.md` files, created by `ytstack:slice-milestone`.

- [x] S01 -- `bin/ytstack-status` prints the progress segment for any directory, from one shared parser that the STATE lint also uses.
- [x] S02 -- The block stays current without hand upkeep and a user can wire the segment into their status line from the documentation.

## Run order

Slices execute sequentially. After each slice, `ytstack:reassess-roadmap` checks if the plan still fits reality.

## How to update this file

- Flip slice checkbox `[ ]` -> `[x]` when its tasks are all `summarize-task`-confirmed
- Update `completed_slices` count
- On milestone completion, flip `status: planned` -> `status: done` and update global ROADMAP.md
27 changes: 27 additions & 0 deletions .ytstack/M021-S01-PLAN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
milestone: M021
slice: S01
project: ytstack
created: 2026-11-11T10:25:52Z
status: done
task_count: 2
completed_tasks: 2
---

# M021-S01 -- Slice Plan

**Goal:** `bin/ytstack-status` prints the progress segment for any directory, from one shared parser that the STATE lint also uses.

## Tasks

- [x] T01 -- `yt_progress_parse` in `hooks/lib/git-ctx.sh` (reads STATE content on stdin; sets state none / ok / bad plus label, done, total, waiting_on) and lint finding W7 in `yt_state_lint` for a malformed block; cases in `tests/git-ctx.test.sh`.
- [x] T02 -- `bin/ytstack-status`: cwd from the status line JSON (`workspace.current_dir`, `cwd`, else `$PWD`), plan progress from the default branch outside it, task pointer from the local `STATE.md`, slice checkbox fallback, `waiting_on` truncation, `NO_COLOR` / `--no-color`, silent non-zero exit outside a project or on a malformed block; new `tests/ytstack-status.test.sh`.

## Done when

All tasks marked `[x]` and verified via `ytstack:summarize-task`.

## Notes

- Claude Code documents no stable path to plugin files for a `statusLine` command: `bin/` is on PATH for the Bash tool only, and `CLAUDE_PLUGIN_ROOT` changes on every update (statusline and plugin manifest reference, read 2026-11-11).
- Considered and dropped: SessionStart maintaining a `~/.ytstack/bin/ytstack-status` link. The hook is read-only by contract and every suite that fires it would need an isolated HOME. The integration snippet in `docs/statusline.md` (S02-T02) resolves the newest installed version itself instead.
43 changes: 43 additions & 0 deletions .ytstack/M021-S01-T01-PLAN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
milestone: M021
slice: S01
task: T01
project: ytstack
created: 2026-11-11T10:27:00Z
status: planned
---

# M021-S01-T01 -- Task Plan

**Summary:** `yt_progress_parse` in `hooks/lib/git-ctx.sh` and lint finding W7 in `yt_state_lint` for a malformed `progress` block.

## Files

- Modify: `hooks/lib/git-ctx.sh` (new function before `yt_state_lint`; W7 inside it; header comment lists W7)
- Modify: `tests/git-ctx.test.sh` (new section after the STATE lint cases)

## What this does

`yt_progress_parse` reads STATE.md content on stdin, so the caller can feed a file or `git show` output. It looks at the frontmatter only (up to the closing `---`, or the first `#` heading when the file has no delimiters) for a `progress:` key followed by indented `label`, `done`, `total` and optional `waiting_on`. Values lose surrounding quotes and a trailing ` # comment`; comment lines and unknown keys inside the block are skipped.

Result variables:

- `YT_PROGRESS`: `none` (no block), `ok`, or `bad`
- `YT_PROGRESS_LABEL`, `YT_PROGRESS_DONE`, `YT_PROGRESS_TOTAL`, `YT_PROGRESS_WAITING`: set only when `ok`
- `YT_PROGRESS_ERRORS`: one line per problem when `bad`

Rules for `ok`: `label` present and at most 16 characters; `done` and `total` are plain digits (at most 9); `total >= 1`; `done <= total`. `progress:` with an inline value is `bad`.

`yt_state_lint` calls the parser on `STATE.md` and adds one warning per error line (W7). No block means no warning.

## Verification

```bash
bash tests/git-ctx.test.sh
```

Success: command exits 0 and shows expected output. Failure: re-read plan, check if spec drifted.

## Done signal

Run `/ytstack:summarize-task` after execution to mark complete and advance STATE.md.
32 changes: 32 additions & 0 deletions .ytstack/M021-S01-T01-SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
milestone: M021
slice: S01
task: T01
project: ytstack
closed: 2026-11-11T10:29:03Z
verification: passed
---

# M021-S01-T01 -- Summary

## Commits

- `d29ab53` M021-S01-T01: add yt_progress_parse and STATE lint finding W7 for the progress block

## Outcome

`yt_progress_parse` reads STATE.md content on stdin and reports `none`, `ok` or `bad` for the optional frontmatter `progress` block, with label, done, total and waiting_on on `ok` and one error line per problem on `bad`. `yt_state_lint` runs it on `STATE.md` and turns each error line into a warning (W7). A project without the block gets no warning.

## Deviations from plan

none

## Follow-ups

none

## Verification

Command: `bash tests/git-ctx.test.sh` -- passed (150 passed, 0 failed; same result under `/bin/bash` 3.2).

Minimal-code review: rung 6. One awk pass instead of a YAML dependency. Left out on purpose: several tracks, a `done`/`open` pair, multi-line YAML scalars.
45 changes: 45 additions & 0 deletions .ytstack/M021-S01-T02-PLAN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
milestone: M021
slice: S01
task: T02
project: ytstack
created: 2026-11-11T10:29:30Z
status: planned
---

# M021-S01-T02 -- Task Plan

**Summary:** `bin/ytstack-status` prints one compact segment for the directory named in the status line JSON.

## Files

- Create: `bin/ytstack-status` (executable)
- Create: `tests/ytstack-status.test.sh`

## What this does

Input: status line JSON on stdin (only `cwd` is used, through `yt_read_stdin`); without usable input the script falls back to `$PWD`. Flag `--no-color`; a non-empty `NO_COLOR` does the same.

Resolution: `yt_git_ctx` + `yt_resolve_yt_dir`. No `.ytstack` or no `STATE.md`: no output, exit 1.

Task pointer: `current_milestone` / `active_slice` / `active_task` from the local `STATE.md`; parts that are `none`, `all` or malformed are left out.

Plan progress: in a project-scope git checkout whose current branch is not the default branch, `STATE.md` is read with `git show` from the newer of `origin/<default>` and the local `<default>`; the default branch comes from `origin/HEAD`, else `main`, else `master`. Otherwise, or when that read yields nothing, the working tree file is used. Local refs only, no network.

Output (one line, exit 0):

- block `ok`: `V2 76% 138/180 · M021/S01/T02 · waiting: <item>` (pointer and waiting part only when present; the item is cut to 32 characters plus `…`)
- no block: `M021/S01/T02 3/7`, the count taken from the task checkboxes of the active slice plan (flat path first, then `yt_find_artifacts`); pointer alone when no slice plan is found
- block `bad`, or neither block nor pointer: no output, exit 1

## Verification

```bash
bash tests/ytstack-status.test.sh
```

Success: command exits 0 and shows expected output. Failure: re-read plan, check if spec drifted.

## Done signal

Run `/ytstack:summarize-task` after execution to mark complete and advance STATE.md.
33 changes: 33 additions & 0 deletions .ytstack/M021-S01-T02-SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
milestone: M021
slice: S01
task: T02
project: ytstack
closed: 2026-11-11T10:31:28Z
verification: passed
---

# M021-S01-T02 -- Summary

## Commits

- `967d90d` M021-S01-T02: add bin/ytstack-status, the status line segment for a ytstack project

## Outcome

`bin/ytstack-status` reads `cwd` from the status line JSON (else `$PWD`), resolves the ytstack project and prints one line: with a `progress` block `V2 76% 138/180 · M021/S01/T02 · waiting: …`, without it the pointer plus the active slice's checkbox count (`M021/S01/T02 1/2`). On a branch other than the default one the block is read with `git show` from the newer of `origin/<default>` and `<default>`; the pointer stays local. It prints nothing and exits 1 outside a project, for a malformed block, and when there is neither block nor pointer. `NO_COLOR` and `--no-color` switch the colour off.

## Deviations from plan

none

## Follow-ups

- `shortcut:` in `bin/ytstack-status`: `waiting_on` is cut by characters of the current locale; under `LC_ALL=C` a multi-byte character at the cut can be split.
- One run takes about 90 ms on this machine (ten runs 0.92 s), most of it the git calls in `yt_git_ctx`. Fine for a status line that is debounced at 300 ms; a cache is the lever if it ever matters.

## Verification

Command: `bash tests/ytstack-status.test.sh` -- passed (31 passed, 0 failed; same under `/bin/bash` 3.2). Live: this worktree printed `M021/S01/T02 1/2`, `/tmp` printed nothing with exit 1.

Minimal-code review: rung 2 for input and resolution (`yt_read_stdin`, `yt_git_ctx`, `yt_resolve_yt_dir`, `yt_find_artifacts` reused), rung 6 for the rest. Left out on purpose: reading `workspace.current_dir` (Claude Code documents it as equal to `cwd`), symlink resolution of the script path, a cache.
27 changes: 27 additions & 0 deletions .ytstack/M021-S02-PLAN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
milestone: M021
slice: S02
project: ytstack
created: 2026-11-11T10:25:52Z
status: done
task_count: 3
completed_tasks: 3
---

# M021-S02 -- Slice Plan

**Goal:** The block stays current without hand upkeep and a user can wire the segment into their status line from the documentation.

## Tasks

- [x] T01 -- `summarize-task` and `quick-task` update the `progress` block when they advance STATE and re-run the lint; skill versions bumped; `bin/ytstack-check` clean.
- [x] T02 -- `docs/statusline.md` (block reference, output forms, two-line integration for Claude Code, other hosts, colour switch); pointers in README, `docs/concept.md` and `docs/codex.md`; CHANGELOG `[Unreleased]` entry.
- [x] T03 -- Verification and close: `bash tests/run-all.sh`, `bash tests/run-all.sh --linux`, `bin/ytstack-check`, live run against this repository and a linked worktree; M021 roadmap, global ROADMAP, DECISIONS and STATE closed.

## Done when

All tasks marked `[x]` and verified via `ytstack:summarize-task`.

## Notes

- Push, release tag and issue closing are operator actions (standing instruction).
35 changes: 35 additions & 0 deletions .ytstack/M021-S02-T01-PLAN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
milestone: M021
slice: S02
task: T01
project: ytstack
created: 2026-11-11T10:32:00Z
status: planned
---

# M021-S02-T01 -- Task Plan

**Summary:** `summarize-task` and `quick-task` update the `progress` block when they advance STATE.

## Files

- Modify: `skills/summarize-task/SKILL.md` (Step 10, checklist item 10, `metadata.version`)
- Modify: `skills/quick-task/SKILL.md` (Step 6 closing paragraph, `metadata.version`)

## What this does

`summarize-task` Step 10: when the frontmatter has a `progress:` block, the same edit adds 1 to `done` if the closed task is an item the block counts (tasks by default; a comment line inside the block names another ledger), raises `total` for a task that was added after the total was set, never writes `done` above `total`, and re-runs `yt_state_lint`. Swarm teammates skip it with the other frontmatter writes and note the pending increment under Follow-ups. No block: nothing happens and none is added.

`quick-task`: same rule in one sentence, limited to a change that completes a counted item.

## Verification

```bash
bin/ytstack-check; bash tests/run-all.sh
```

Success: checker without failures (exit 0 or 2), all suites pass. Failure: re-read plan, check if spec drifted.

## Done signal

Run `/ytstack:summarize-task` after execution to mark complete and advance STATE.md.
30 changes: 30 additions & 0 deletions .ytstack/M021-S02-T01-SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
milestone: M021
slice: S02
task: T01
project: ytstack
closed: 2026-11-11T10:33:03Z
verification: passed
---

# M021-S02-T01 -- Summary

## Commits

- `b414072` M021-S02-T01: summarize-task and quick-task keep the STATE progress block current

## Outcome

`summarize-task` Step 10 now updates a `progress:` block in the same STATE edit: plus one on `done` for a counted task, `total` raised for a task added later, never `done` above `total`, lint re-run. Swarm teammates skip it and note the pending increment. `quick-task` carries the same rule for a counted change. Both skills are at 0.1.1.

## Deviations from plan

none

## Follow-ups

- The instruction is prose for the agent, not code. No eval case covers it yet; add one to `evals/` when the block is in use on a real project.

## Verification

Command: `bin/ytstack-check; bash tests/run-all.sh` -- passed (checker `OK (with 27 warning[s])`, the same count as `main`; 13 suites, `ALL SUITES PASSED`).
Loading
Loading