# nobrainer-tech-flow 2.0.1 verification record

Source version: 2.0.1. Publication is a separate check against the public tag
and release archive; this document alone does not establish distribution.

Corrections made by 2.0.2 (see its [record](v2.0.2.md)): the statements below that
a symlink-loop destination is reported (not on Python 3.13), that a Claude import is
recognised "only when it is a plain, stand-alone one" (code spans, nested fences,
comments, raw HTML and more were still mistaken for imports; 2.0.2 recognises only a
file that holds nothing but the import), that a non-absolute environment variable is
an error (for every client, not only the one that reads it; a blank one also counted
as unset) and that copy mode ignores bytecode (any `.pyc`, not only `__pycache__`).

2.0.1 is a corrective release for 2.0.0. It adds no skill and keeps the
eighteen-skill portfolio. The only skill-text change with a behavioural effect is
a fallback for a missing `nobrainer-sessions` (see "Documentation and skills").

## What changed

Client adapters

- Codex marketplace entry: the plugin is named `nobrainer-tech-flow` like its
  manifest and uses a local source, so `codex plugin add` finds and installs it.
  Before, neither plugin name matched both files.
- Codex manifest: the two default prompts fit the 128-character limit; longer
  ones are ignored by the client.
- OpenCode: the bootstrap is still added after a compaction, when the first user
  message has no text part, and a missing bootstrap file no longer throws.
- Pi: dead state removed; a missing bootstrap file no longer fails a request.
- Hooks: `hooks/session-start`, `hooks/run-hook.cmd` and `adapters/bootstrap.md`
  are pinned to LF, so a Windows checkout with `core.autocrlf=true` still runs the
  scripts and the bootstrap reaches the model without carriage returns.
  `session-start` accepts a backslash script path when run under Git Bash, which
  is how the Windows batch half of the wrapper starts it. `run-hook.cmd` itself
  is unchanged and must stay POSIX-sh compatible, because hosts start it
  through `/bin/sh`.

Installers and setup

- `install_skills.py`: copy mode no longer calls `ctypes.CDLL(None)` on Windows;
  repeating a copy install over an identical copy is a no-op, ignoring bytecode
  and `.DS_Store` litter, and a foreign directory is rejected by comparing names
  and sizes before any file is read; a destination that is a file, a symlink loop
  or unreadable, and a dangling link, are reported instead of crashing; the
  preview names links from a selected skill to a skill that will be absent.
- Claude Code `CLAUDE_CONFIG_DIR` and OpenCode `XDG_CONFIG_HOME` select the skills
  directory, and Codex `CODEX_HOME` and the same two select the instruction file,
  when `--home` is not given. An explicit `--home` ignores them. A value that is
  not an absolute path is an error, and a blank one counts as unset.
- `install_personalization.py`: a Claude file that imports the Codex global file
  is treated as inheriting only when the import is a plain, stand-alone one and
  the Codex file holds the block; otherwise the block is written and the reason
  printed. Codex's `AGENTS.override.md` blocks the write it would shadow. The new
  `--keep-options` flag keeps earlier auto-update, session-restart and wiki-root
  settings, recognising a grant only as the exact line the installer writes for it
  (so a `--preferences` value quoting the wording cannot forge one), and the block
  no longer carries a stray blank line.
- `recommend_flow_setup.py`: without a terminal (including a closed stdin) and with
  an answer missing it stops with `INPUT_REQUIRED` and the flags to pass, instead
  of hanging or crashing; it follows the same environment variables, resolves a
  relative `--home`, always keeps earlier options, treats a symlink loop as a
  conflict and says what to do when the Codex override file blocks the write.
- All three scripts write UTF-8 to a pipe, so paths and instruction-file lines
  outside the Windows code page no longer abort them, and the guided setup reads
  the `gh` output as UTF-8.
- `session_title.py`: the default UTC title no longer needs a time-zone database,
  which Windows does not ship.
- `check_public_commit.py`: decodes Git output as UTF-8 and reports a missing Git.

Upgrading

- If you ran the guided setup with 2.0.0 while `CLAUDE_CONFIG_DIR` or
  `XDG_CONFIG_HOME` was set, 2.0.0 had written to the default location instead.
  Re-running with 2.0.1 then stops and says so; run the same command with
  `--rollback --apply` once, or pass `--home` to keep that location.
- The next personalization run rewrites the managed block once (the stray blank
  line is gone) and shows the difference in its preview.

Documentation and skills

- README lists all eighteen skills, states six compatibility levels and no longer
  says 1.6 is current; `CLAUDE.md`/`AGENTS.md` lose stray backslashes; one
  machine path is removed from `tasks/todo.md`.
- `docs/INSTALL.md`: correct code fences, the guided-setup flags, the Claude Code
  and Codex plugin commands and invocation forms, a subset example that keeps
  what the core skill links to, one-channel-per-client guidance, and a Windows
  section. Adapter descriptions match the code, and Cursor is no longer called
  tested.
- Three small skill-text edits, none evaluated with model runs (none was
  possible here):
  - `references/worktrees.md` and `references/daily-update.md` name their helper
    scripts through `<flow-skill-dir>`, as the other references do, instead of a
    path that exists only inside this repository.
  - `nobrainer-codex-context` starts its read-only probe from the project through
    `<context-skill-dir>`. The old text said to run it from the skill directory,
    where it inspected the skill folder and reported `MISSING`.
  - The core skill runs the Sessions startup step only when `nobrainer-sessions`
    is installed and otherwise stays in MAIN. Before, a subset install without
    Sessions pointed at a file that does not exist. Nothing changes when Sessions
    is installed.

Release gates

- The skill `VERSION` file and `package-lock.json` must match the manifests;
  `check_flow_update.py` reads the former.
- A cross-skill link map fails when a skill starts linking into another skill,
  the subset example in `docs/INSTALL.md` must have no dead links, and the README
  table must list every skill.
- CI syntax-checks the skill helper scripts and runs a Windows job.

## Reproduce the repository checks

From the exact reviewed release checkout, run:

```sh
python3 scripts/validate_skills.py --suite
python3 -m unittest discover -s tests -q
```

The Windows job runs the validators plus `tests.test_windows_smoke` and
`tests.test_adapters`. It passed on GitHub's `windows-latest` (Git Bash, Python
3.11, Node 22) for this source, including the `cmd` wrapper reaching the bootstrap
through Git Bash and a copy-mode install. The whole suite is not run there: some
historical evidence tests compare text byte for byte and assume LF checkouts.

## Evidence limits

These checks establish local helper behavior, source contracts and the client
readbacks named in the [compatibility record](../COMPATIBILITY.md). They do not
prove that a client routes a task through Flow, that a model followed a skill, or
that Cursor, Gemini CLI, Kimi Code, OpenCode or Pi accept the adapters at
runtime; the OpenCode synthetic text part follows the message shape simulated in
the tests, not a real OpenCode session. Known gaps that this release does not address are the cost of starting
Flow on a trivial task, the worktree-per-task default, and the differences between
the Flow and Dispatcher ledgers.
