Skip to content

Say in the position when the workspace keeps a progress board - #339

Merged
takashi-matsuyama merged 3 commits into
mainfrom
feat/orient-board-line
Oct 9, 2026
Merged

takashi-matsuyama merged 3 commits into
mainfrom
feat/orient-board-line

Conversation

@takashi-matsuyama

Copy link
Copy Markdown
Member

Summary

basou orient now says when the workspace keeps a progress board, and how to update it. When the manifest declares the workspace's own repo private and board/board.yaml is there, the position's "where you are now" ends with one line:

- Progress board: last record 2026-10-08 (3d ago), axis v2. To update it, follow `basou board guide`.
  • What it says: when the last record was written and how long ago, or that there is none yet; the axis version the declaration gives; and to follow basou board guide.
    • The time comes from the record's ULID file name. The day is taken from the Date's local fields, so it is the host's day even under a TZ with no zone name.
    • The line is in the anchor's language (view-strings.ts).
  • Who writes it: basou orient, basou refresh, and the SessionStart hooks. The hooks hand the same position to a Claude Code or Codex session, so an agent learns of the board, and where its steps are, with no skill of its own.
  • What it reads: only the names of the files in records/ (directories passed over) and the declaration's axis.version, with YAML read as basou board reads it (1.2 only, no key twice, no unresolved tag).
    • A board.yaml over 128 KiB is not read: a position is rendered at every session start, under a time limit.
    • A board that cannot be read is said to be so ("its records cannot be read", "axis version unknown"). It never fails the position, never changes an exit code, and changes the hooks' output by that line only.
  • The name check: the line is basou's own words around a date and a version. The check for other registered workspaces' names (orient's advisory and the hook's withholding) blanks the line before scanning, keeping line numbers. Without that, a workspace named like one of its words would silence the hook's position.
  • No board: a workspace with no board gets no line.
  • @basou/core (Internal): glanceBoard, BOARD_GLANCE_MAX_BYTES and isPositionBoardLine; renderOrientation takes board.

orient's prose is outside the compatibility contract. compatibility.md allows a guaranteed command to show what an experimental one wrote, in prose. No change to compatibility.md or the README.

Why

With the guide (#337) and init (#338), a judged board needs no skill of its own. An agent still has to learn that the board exists and where its steps are. The position is what every session in the workspace reads first, so one line there reaches Claude Code and Codex alike.

Verification

  • CI steps, run locally with exit codes: pnpm -r build, pnpm typecheck, pnpm lint (the existing 4 warnings only), pnpm lint:lang, pnpm lint:paths, pnpm test:scripts: all 0. pnpm test:coverage is 0 under Node 24 and under Node 20, which CI runs.
    • The board, orient, hook, refresh and view tests pass under TZ=America/New_York and Asia/Tokyo too.
  • Tests:
    • the line in both languages, with a record, with none, and with unreadable records or axis;
    • its day under TZ=Asia/Tokyo and a zone with no name (JST-9);
    • the glance against broken YAML: an unclosed flow, a duplicate key, %YAML 1.1, an unresolved tag;
    • the size cap, at the limit and one byte over;
    • records that are a file, a link or a directory bearing a record's name;
    • orient with stderr empty, and a board not declared private;
    • basou refresh writing the line;
    • the hook's position kept when another registered workspace is named guide.
  • Mutations: 9 on the first version and 7 on the review's fixes, applied one at a time. All are caught.
  • By hand, in a scratch workspace: orient and hook session-start (with a throwaway portfolio) both print the line.

Review

One round of convergent review (review only), with the decided scope given as fixed. 5 findings (low to low-medium) and a few details, all fixed in the third commit:

  • YAML that basou board refuses still gave an axis version;
  • the line's words could make the hook withhold the whole position;
  • basou refresh rewrote orientation.md without the line;
  • a very large board.yaml stalled orient and the hook;
  • a POSIX-style TZ gave the UTC day;
  • a directory bearing a record's name counted as a record.

Not taken up, as design questions:

  • dating the line by the declaration's time_zone rather than the host's;
  • a version shown when YAML parses but the declaration does not;
  • path: ./ not taken as the anchor (pre-existing).

Checklist

  • Branch is rebased on main.
  • One topic (the line; later commits are its review's fixes).
  • Tests cover the change (happy path and failure modes).
  • pnpm lint, pnpm typecheck, and pnpm test are all green locally.
  • CHANGELOG.md ## Unreleased updated.
  • CLI stderr stays pathless (no new error messages).

🤖 Generated with Claude Code

takashi-matsuyama and others added 3 commits October 9, 2026 18:13
When the manifest declares the workspace's own repo private and
board/board.yaml is there, orient's "where you are now" ends with one
line: when the last record was written and how long ago (or that there
is none), the axis version, and to follow basou board guide. The
SessionStart hooks hand the same position to a session, so an agent
learns of the board and where its steps are without a skill of its own.

Only the records' names and the declaration's axis.version are read,
loosely: a board that cannot be read is said to be so and never fails
the position, its exit code or the hooks' output. A workspace with no
board gets no line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Read board.yaml as basou board reads YAML (1.2 only, no key twice, no
  tag left unresolved): one it would refuse gives no axis version. A
  board.yaml over 128 KiB is not read: the position is rendered at every
  session start, under a time limit.
- basou refresh writes the line too, so the position is the same
  whichever command wrote it last.
- The scan for other workspaces' names passes over the line, which is
  basou's own words around a date and a version: a workspace named like
  one of its words no longer silences the hook's position.
- The record's day is the one on this host's clock, from the Date's own
  local fields, which follow TZ where the zone has no name.
- A directory that bears a record's name is not counted as one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@takashi-matsuyama
takashi-matsuyama merged commit dc3cf6e into main Oct 9, 2026
8 checks passed
@takashi-matsuyama
takashi-matsuyama deleted the feat/orient-board-line branch October 9, 2026 10:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant