Fixture run — the development half of AC-13¶
What this is: the executor's development fixture, run to build AC-2, AC-3, AC-4, AC-6 and AC-8 against a real external corpus instead of against this repository. What this is NOT: acceptance evidence. AC-13 half two is the owner's own run on a real project, filed at task root as
FIELD-REPORT__TFW-60__second_external_update.md. This file does not close it, and the RF reports half two as unmet. Full transcript: fixture_run.txt
The fixture¶
| Property | Value |
|---|---|
| Source corpus | KZ-IT-telegram-list at c919640 — the commit before its own 2.0.0 update |
| Cloned to | the session scratch directory. The live project was never written to |
| TFW version | 1.3.0 |
| Payload source | this repository at 1079020, by git archive — a commit SHA, not a tag |
| Update performed | 1.3.0 → 2.0.0-dirty.2, following update.md and .tfw/migrations/2.0.0.md only |
Why this corpus and not a synthetic one: it carries F3, F4 and F6 in one tree.
- board at
tasks/README.mdunder## Board, not the root README — F3 TFW-01_awesome_list_restructureandTFW-02_enhanced_validationbesideTFW-3__tfw_initandTFW-4__showcase_reorg— mixed identifier grammar, F4- no
task_containers, andinitial_seq: 3— F6
Outcome¶
| Check | Result |
|---|---|
Update completed following only update.md and the guide |
✅ |
| Files hand-carried from outside the payload | 0 |
Framework files edited inside .tfw/ |
0 (see below) |
--check project on the migrated fixture |
exit 0 |
| Board rows accounted for | 4 of 4, each named individually |
| Task directories accounted for | 4 of 4 — 2 matched, 2 reported unresolved |
The one file that differed from the payload was
.tfw/scripts/__pycache__/gen_index.cpython-313.pyc — Python bytecode written by running
the tool, not an edit. It produced a real finding, below.
What each finding's fix did on a real corpus¶
F3 — the board is found where the project keeps it¶
Run with defaults, the migration refused and named relocation first, with the exact flags this fixture needed:
board source: git show HEAD:README.md -> 0 data rows
REFUSING: git show HEAD:README.md yielded zero rows under the heading '## Task Board'.
Three causes, in the order they actually occur:
1. the board is ELSEWHERE -- ... --board tasks/README.md
2. the heading differs --board-heading '## Board'
3. the board was REMOVED --board-rev <commit-before-removal>
The shipped message offered only --board-rev, which sends a reader to diagnose a removed
board when the board is merely elsewhere. With the flags: 4 data rows.
The row parser was not touched, and did not need to be.
F4 — two directories stop being called ideas¶
The failing run reported "2 task directories where 4 exist" and rendered both
single-underscore directories under a heading reading "They are ideas, not work in
progress", with backlog idea, never started in the manifest. Both hold completed HL, TS
and RF traces.
Now:
2 matched row and directory both exist
0 board-only a row with no directory at all
2 unresolved a row whose directory the grammar rejects
0 unresolved a rejected directory no row names
0 directory-only a directory with no row
backlog idea, never started appears nowhere in the manifest. The generated index has no
Backlog section at all, and both directories appear under Unresolved inputs with a
reason that talks about the name and asserts nothing about whether work happened:
directory name matches neither identifier grammar … Board row
TFW-01names it. Nothing further is asserted about it: rename it by hand to the recognized grammar to have it picked up
The manifest and the index agree, because both read one classification. Every identifier still resolves by name:
| # | Identifier | Resolves to |
|---|---|---|
| 1 | TFW-01 |
snapshot + directory whose name the grammar rejects + index (unresolved) |
| 2 | TFW-02 |
snapshot + directory whose name the grammar rejects + index (unresolved) |
| 3 | [TFW-3](../../../TFW-3__readme_public_readiness/HL-TFW-3__readme_public_readiness.md) |
snapshot + task directory + index (unresolved or closed) |
| 4 | [TFW-4](../../../TFW-4__framework_cleanup/HL-TFW-4__framework_cleanup.md) |
snapshot + task directory + status.md → index |
F8 — the source is a committed revision¶
board source: git show HEAD:tasks/README.md, printed on every run. The working tree is
--working-tree, and it was not needed here.
F1 — the depth was load-bearing, and this is the only test that shows it¶
parents[2] resolves correctly from .tfw/scripts/ by coincidence, so a source-only
move would have passed every test in this repository. The observable test is the tools copied
to a different depth inside a project:
| Placed at | parents[2] would give |
The tool resolved |
|---|---|---|
tools/ |
…/fixture — wrong, outside the project |
…/fixture/consumer ✅ |
tools/tfw/ |
…/fixture/consumer — right, by luck |
…/fixture/consumer ✅ |
a/b/c/d/ |
…/consumer/a/b — wrong |
…/fixture/consumer ✅ |
Depth arithmetic would have been wrong in two of three placements. It was also silently
wrong: tools/ resolves to a directory outside the project, where a run would have written
an index for a tree nobody asked about.
AC-10 — the pristine-tag diff, and whose tag it is¶
The fixture has no TFW version tags of its own; the tag lives in the source. Run against
the source's v1.3.0:
CUSTOMIZED .tfw/knowledge_state.yaml
CUSTOMIZED .tfw/project_config.yaml
customized files: 2
Two files out of ~38, and both are the ones that are supposed to be project-owned. Every
other .tfw/ file was byte-identical to the release and could simply be overwritten. This is
the check that turned three declared manual merges into zero on the first real update.
F6 — the two decisions arrived as decisions¶
task_containers was chosen ([tasks] — the existing directory keeps its name and its
tasks) and initial_seq: 3 was deleted, both because update.md named them rather than
leaving them to inference.
Two findings the fixture produced that no test here could have¶
1. The first command the guide gives died on a Windows console · was a blocker¶
File "…/encodings/cp1252.py", line 19, in encode
UnicodeEncodeError: 'charmap' codec can't encode character '✅' in position 1679
migrate_board.py without --manifest prints the manifest to stdout, and the manifest
quotes the board verbatim — so it carries whatever characters the project's board
carried. On a console whose codepage is cp1252, print() raises and the run dies before
printing anything useful.
Runtime messages are ASCII by rule here, and a test enforces it. Content is not, and
cannot be — the whole value of the verbatim block is that it is exact. Fixed by making both
entry points' streams tolerant (errors="replace") while files keep encoding="utf-8" and
stay byte-exact. Two tests added: one drives the tool as a subprocess with
PYTHONIOENCODING=cp1252, one asserts the written snapshot keeps every row's exact bytes.
Not findable by inspection here: this repository's own board is gone, so nothing in its test corpus prints a real board to a real console.
2. Copying a payload adds and overwrites, but never removes · medium¶
RETIRED: .tfw/templates/topic_file.md
The template moved to templates/knowledge/topic.md. The old path stayed in the fixture's
.tfw/ because copying a payload over an existing one cannot delete anything. A second copy
of a template is a second thing that can be edited by mistake.
The guide now carries the command that finds them.
3. __pycache__ dirties a receiving project's tree · low¶
Running a shipped Python tool writes .tfw/scripts/__pycache__/. This repository's
.gitignore covers it; a project whose ignore rules never needed a Python entry will see the
payload dirty its own tree on first use. One line added to the guide.
What was confusing, not only what worked¶
update.mdStep 3a's loop reads from the source, not from the receiving project, and the first attempt got that backwards. The step now says whose tag; it needed saying twice before it stuck.- The
--boardand--board-headingflags are two decisions that arrive as one. The refusal names both, which is why the second attempt worked — but a reader who fixes only the path gets zero rows again and has to read the refusal a second time. - Nothing tells the operator to delete retired framework files until the guide says so,
and there is no check that reports one.
--check projectcould grow that; it is filed as an observation rather than added, because a payload-completeness check that also asserts payload minimality is a different claim.
What is deliberately not closed¶
AC-13 half two. This is a clone in a scratch directory, driven by the same agent that
wrote the code. It is a development fixture and it is not acceptance evidence — the point of
DoD 19 is a project whose operator is not the author. The live KZ-IT-telegram-list was
never written to: it belongs to its owner, and a second agent writing into it is the defect
this task exists to end.
Fixture run for TFW-60 Phase AA · 2026-08-27 · payload at 1079020