Reading Tree
Use this skill when the user wants to transform an article or chapter into a linked reading interface:
- The tree must preserve the source order.
- Clicking a node must jump to and highlight the covered source paragraphs.
- Clicking a source paragraph must jump back to the best matching node.
- The result must stay suitable for full reading, not just skimming.
Outcome
Produce a workspace that can build:
site/data/source.js
site/data/tree-data.js
- a static interactive site in
site/
The generated site includes:
- bidirectional node/paragraph linking for reading
- global search where text and outline labels use JavaScript regex, while roles stay plain
AND as the default search operator, with explicit uppercase OR
- optional field prefixes such as
role:example
Shared tooling lives in scripts/.
For online tools such as ChatGPT or Claude.ai that cannot serve the generated UI directly, provide a .zip archive of the full site/ folder and tell the user to extract it and open site/index.html in a browser. Do not hand off only index.html, because it depends on sibling assets.
The default site template opens locally, but it is not fully self-contained in the strict offline/privacy sense: when online, it requests Google Fonts for typography. If those requests are blocked, the browser falls back to local serif fonts and the UI still works.
The reusable workspace scaffold lives in assets/workspace-template/.
Workflow
- Copy
assets/workspace-template/ into a fresh workspace.
- Save the source text as
article.txt, preserving the original paragraph boundaries by default. Prefer one source paragraph per line. Only split one original paragraph into multiple lines when it is very long or contains an obvious internal semantic shift.
- Inspect
article.txt with real line numbers from the terminal, for example nl -ba article.txt.
- For long files, inspect windows such as
sed -n '120,180p' article.txt | nl -ba -v120 instead of counting lines in model context.
- Create
splits.json with semantic paragraph start lines only. If article.txt already uses one source paragraph per line, the split list will often start on every non-empty line.
- Run
python3 reading-tree/scripts/build.py <workspace> --step source and inspect site/data/source.js.
- Create
tree.json after the paragraph split is stable. Every node must declare at least one non-empty broad role via roles.
- Run a structure audit against
references/authoring.md, especially Breadth Control and Final Structure Check.
- Materialize that review as a markdown table before continuing. Use one row per non-leaf sibling group in tree order so grouping choices are explicit. Top-level nodes are mandatory rows.
- Regroup until the structure audit table is clean.
6 is a ceiling, not a target for normal-length texts. For substantially longer texts, treat the breadth numbers as defaults rather than hard caps, but justify any exception in the audit table.
- Prefer adding intermediate grouping nodes over coarsening paragraph splits when reducing breadth.
- During structural iteration, run
python3 reading-tree/scripts/validate.py <workspace> after each structural edit as cheap feedback.
- Run a mandatory final label lint pass against
references/authoring.md, especially the Meaning Fidelity Check and Final Label Check sections. Inspect every node label one by one in tree order.
- Materialize that review as a markdown table before continuing. Use one row per label, and include both style columns and meaning-fidelity columns from
references/authoring.md, plus the roles columns for every row. Treat the table as the required reasoning scaffold, not as optional presentation.
- Rewrite every weak or semantically overstated label before continuing. Update the table until every row passes. Do not continue if even one row still fails.
- After the structure audit table and label audit table are both clean, run
python3 reading-tree/scripts/validate.py <workspace> again as the required final validation pass.
- Run
python3 reading-tree/scripts/build.py <workspace> --step all.
- To inspect or hand off the result, note that
site/index.html can be opened directly in a browser, or cd site/ and serve it with python3 -m http.server 8000 --bind 127.0.0.1. For online tools such as ChatGPT or Claude.ai that cannot serve the UI themselves, provide a .zip archive of the full site/ folder and instruct the user to extract it and open site/index.html. Do not provide only index.html. Also mention that the default template requests Google Fonts when online; if those requests are blocked, the browser falls back to local serif fonts.
- If serving locally, tell the user to open
http://127.0.0.1:8000/ in a browser. Only launch a browser from the agent if the user explicitly asks for that.
Non-Negotiable Rules
- Preserve the original narrative order in every sibling list.
- Do not repeat source text in assistant output after it is saved to
article.txt.
- Keep per-article edits limited to
article.txt, splits.json, and tree.json unless the user explicitly asks for a site template change.
- Preserve the source paragraphing in
article.txt unless a paragraph is so long, or so internally split in function, that one line would make linking or reading clumsy.
- Do not subdivide source paragraphs just to make the tree cleaner or to avoid adding intermediate grouping nodes.
- Take split line numbers from a numbered file view such as
nl -ba article.txt, not by mentally counting lines from model context.
- If a leaf node is still too long after it covers a single paragraph, go back and refine
splits.json.
- Inspect
site/data/source.js after splitting. scripts/validate.py checks structure, but it will not catch a semantically wrong off-by-one split if the ranges remain self-consistent.
- Treat overloaded breadth as unfinished structure. If the root has more than
6 children, or any sibling group has more than 6, regroup before build unless there is a strong reason not to.
- Treat
3–5 top-level nodes as the preferred target. 6 is a ceiling, not a success condition.
- For substantially longer texts, treat the breadth numbers as defaults, not hard caps, and explain any justified exception in the structure audit table.
- Reduce breadth by adding intermediate grouping nodes before you consider coarsening paragraph splits.
- A structure review is not complete until the model has produced a structure audit table and resolved every flagged row.
- The structure audit table must record grouping and breadth checks for every non-leaf sibling group.
- Run
scripts/validate.py after every structural edit for cheap feedback, and run it again after the structure audit table and final label audit table are clean as the required final validation pass.
- Every node must declare at least one non-empty broad role in
roles.
- Treat the final label lint pass as a hard gate, not a suggestion.
- Do not treat
scripts/validate.py or any future automated lint as a substitute for the label audit table. The model must still inspect every label one by one and record the judgement explicitly.
- The final label lint pass is not complete until the model has produced a label audit table with one row per label and one column per condition.
- The label audit table must also record the role checks for each row. Do not move that review into a separate role-only table unless the user asks for it.
- If the response omits the per-label table, the label review has not been done.
- A tree is not complete if even one label still uses weak pronoun-led openings or filler scaffolding such as
He ..., It ..., This ..., There is ..., or The author says ....
- A tree is not complete if even one label is stronger, sharper, or more accusatory than its covered source paragraphs justify.
- A tree is not complete if a parent label states a shared property that is not actually true of every child under it.
- If the delivery surface cannot serve the generated UI directly, do not pretend it can. Hand off a
.zip archive of the full site/ folder and instruct the user to extract it and open site/index.html locally. Never hand off only index.html.
Read These References
references/schema.md for the file formats and validation constraints.
references/authoring.md for splitting, naming, weighting, and structure rules.
references/ui-contract.md for the required linked-reading interaction model.
1---2name: reading-tree3description: Turn an article or book chapter into an order-preserving interactive outline tree with bidirectional links between tree nodes and full-text paragraphs. Use when the user wants a detailed reading structure, not a standalone summary.4---56# Reading Tree78Use this skill when the user wants to transform an article or chapter into a linked reading interface:910- The tree must preserve the source order.11- Clicking a node must jump to and highlight the covered source paragraphs.12- Clicking a source paragraph must jump back to the best matching node.13- The result must stay suitable for full reading, not just skimming.1415## Outcome1617Produce a workspace that can build:1819- `site/data/source.js`20- `site/data/tree-data.js`21- a static interactive site in `site/`2223The generated site includes:2425- bidirectional node/paragraph linking for reading26- global search where text and outline labels use JavaScript regex, while roles stay plain27- `AND` as the default search operator, with explicit uppercase `OR`28- optional field prefixes such as `role:example`2930Shared tooling lives in `scripts/`.31For online tools such as ChatGPT or Claude.ai that cannot serve the generated UI directly, provide a `.zip` archive of the full `site/` folder and tell the user to extract it and open `site/index.html` in a browser. Do not hand off only `index.html`, because it depends on sibling assets.32The default site template opens locally, but it is not fully self-contained in the strict offline/privacy sense: when online, it requests Google Fonts for typography. If those requests are blocked, the browser falls back to local serif fonts and the UI still works.3334The reusable workspace scaffold lives in `assets/workspace-template/`.3536## Workflow37381. Copy `assets/workspace-template/` into a fresh workspace.392. Save the source text as `article.txt`, preserving the original paragraph boundaries by default. Prefer one source paragraph per line. Only split one original paragraph into multiple lines when it is very long or contains an obvious internal semantic shift.403. Inspect `article.txt` with real line numbers from the terminal, for example `nl -ba article.txt`.414. For long files, inspect windows such as `sed -n '120,180p' article.txt | nl -ba -v120` instead of counting lines in model context.425. Create `splits.json` with semantic paragraph start lines only. If `article.txt` already uses one source paragraph per line, the split list will often start on every non-empty line.436. Run `python3 reading-tree/scripts/build.py <workspace> --step source` and inspect `site/data/source.js`.447. Create `tree.json` after the paragraph split is stable. Every node must declare at least one non-empty broad role via `roles`.458. Run a structure audit against `references/authoring.md`, especially `Breadth Control` and `Final Structure Check`.469. Materialize that review as a markdown table before continuing. Use one row per non-leaf sibling group in tree order so grouping choices are explicit. Top-level nodes are mandatory rows.4710. Regroup until the structure audit table is clean. `6` is a ceiling, not a target for normal-length texts. For substantially longer texts, treat the breadth numbers as defaults rather than hard caps, but justify any exception in the audit table.4811. Prefer adding intermediate grouping nodes over coarsening paragraph splits when reducing breadth.4912. During structural iteration, run `python3 reading-tree/scripts/validate.py <workspace>` after each structural edit as cheap feedback.5013. Run a mandatory final label lint pass against `references/authoring.md`, especially the `Meaning Fidelity Check` and `Final Label Check` sections. Inspect every node label one by one in tree order.5114. Materialize that review as a markdown table before continuing. Use one row per label, and include both style columns and meaning-fidelity columns from `references/authoring.md`, plus the roles columns for every row. Treat the table as the required reasoning scaffold, not as optional presentation.5215. Rewrite every weak or semantically overstated label before continuing. Update the table until every row passes. Do not continue if even one row still fails.5316. After the structure audit table and label audit table are both clean, run `python3 reading-tree/scripts/validate.py <workspace>` again as the required final validation pass.5417. Run `python3 reading-tree/scripts/build.py <workspace> --step all`.5518. To inspect or hand off the result, note that `site/index.html` can be opened directly in a browser, or `cd site/` and serve it with `python3 -m http.server 8000 --bind 127.0.0.1`. For online tools such as ChatGPT or Claude.ai that cannot serve the UI themselves, provide a `.zip` archive of the full `site/` folder and instruct the user to extract it and open `site/index.html`. Do not provide only `index.html`. Also mention that the default template requests Google Fonts when online; if those requests are blocked, the browser falls back to local serif fonts.5619. If serving locally, tell the user to open `http://127.0.0.1:8000/` in a browser. Only launch a browser from the agent if the user explicitly asks for that.5758## Non-Negotiable Rules5960- Preserve the original narrative order in every sibling list.61- Do not repeat source text in assistant output after it is saved to `article.txt`.62- Keep per-article edits limited to `article.txt`, `splits.json`, and `tree.json` unless the user explicitly asks for a site template change.63- Preserve the source paragraphing in `article.txt` unless a paragraph is so long, or so internally split in function, that one line would make linking or reading clumsy.64- Do not subdivide source paragraphs just to make the tree cleaner or to avoid adding intermediate grouping nodes.65- Take split line numbers from a numbered file view such as `nl -ba article.txt`, not by mentally counting lines from model context.66- If a leaf node is still too long after it covers a single paragraph, go back and refine `splits.json`.67- Inspect `site/data/source.js` after splitting. `scripts/validate.py` checks structure, but it will not catch a semantically wrong off-by-one split if the ranges remain self-consistent.68- Treat overloaded breadth as unfinished structure. If the root has more than `6` children, or any sibling group has more than `6`, regroup before build unless there is a strong reason not to.69- Treat `3–5` top-level nodes as the preferred target. `6` is a ceiling, not a success condition.70- For substantially longer texts, treat the breadth numbers as defaults, not hard caps, and explain any justified exception in the structure audit table.71- Reduce breadth by adding intermediate grouping nodes before you consider coarsening paragraph splits.72- A structure review is not complete until the model has produced a structure audit table and resolved every flagged row.73- The structure audit table must record grouping and breadth checks for every non-leaf sibling group.74- Run `scripts/validate.py` after every structural edit for cheap feedback, and run it again after the structure audit table and final label audit table are clean as the required final validation pass.75- Every node must declare at least one non-empty broad role in `roles`.76- Treat the final label lint pass as a hard gate, not a suggestion.77- Do not treat `scripts/validate.py` or any future automated lint as a substitute for the label audit table. The model must still inspect every label one by one and record the judgement explicitly.78- The final label lint pass is not complete until the model has produced a label audit table with one row per label and one column per condition.79- The label audit table must also record the role checks for each row. Do not move that review into a separate role-only table unless the user asks for it.80- If the response omits the per-label table, the label review has not been done.81- A tree is not complete if even one label still uses weak pronoun-led openings or filler scaffolding such as `He ...`, `It ...`, `This ...`, `There is ...`, or `The author says ...`.82- A tree is not complete if even one label is stronger, sharper, or more accusatory than its covered source paragraphs justify.83- A tree is not complete if a parent label states a shared property that is not actually true of every child under it.84- If the delivery surface cannot serve the generated UI directly, do not pretend it can. Hand off a `.zip` archive of the full `site/` folder and instruct the user to extract it and open `site/index.html` locally. Never hand off only `index.html`.8586## Read These References8788- `references/schema.md` for the file formats and validation constraints.89- `references/authoring.md` for splitting, naming, weighting, and structure rules.90- `references/ui-contract.md` for the required linked-reading interaction model.