Language: English | 简体中文
STORY turns years of graduate research into one coherent, defensible, and deposit-ready master's thesis or doctoral dissertation. It keeps the manuscript, research evidence, publication reuse, degree requirements, chapter plans, contribution and claim records, committee feedback, defense materials, corrections, and deposit history in predictable locations. Researchers and AI writing agents work from the same repository-owned instructions, so the thesis can be resumed across sessions and examined long after a particular chat has disappeared.
The central contract is provenance. Every quantitative or comparative statement in the thesis traces to a fingerprinted file under mates/ or remains visibly unresolved as \todo{...}; every assertion about cited work is checked against a reading note or imported source; every degree contribution records its evidence, chapter, publication, and attribution boundaries. STORY therefore treats a thesis as a synthesis of research rather than a stack of papers pasted together.
STORY has two layers: this repository is the template; one degree thesis = one instance, created by cloning the template or installing its skeleton into an existing thesis repository with execs/update.sh --adopt. An instance may import any number of STAR research repositories, STAGE paper repositories, other STORY theses, and manually registered sources. The pairing is optional—STORY also works as a standalone thesis repository.
- Contents
- STAR · STAGE · STORY
- What STORY provides
- Project structure
- Thesis template
- Quick start
- Writing workflow
- The path from research to deposit
- Evidence, attribution, and the claim ledger
- Degree milestones
- Agent harnesses
- Project memory
- Updating STORY skills and workflow docs
- Project conventions
- Adapting STORY to a thesis
- Requirements
- Change log
- License
The three projects cover successive scales of a researcher's work. Use any one independently, or connect them through fingerprinted evidence.
| Project | Scope | Links |
|---|---|---|
| STAR — Systematic Toolchain for AI Research | Runs one research project from idea through reproducible experiments and paper-ready evidence. | Website · GitHub |
| STAGE — Systematic Toolchain for Authoring, Guiding, and Editing | Turns one research contribution into a traceable paper, review cycle, and submission package. | Website · GitHub |
| STORY — Systematic Toolchain for Organizing Research over Years | Shapes graduate research into a defensible master's thesis or doctoral dissertation, defense, and deposit. | Current project · Website · GitHub |
The handoff is one-way and auditable: STAR produces research records and results; STAGE turns a contribution into a paper and its review history; STORY snapshots the relevant artifacts as read-only evidence and synthesizes them at degree scale. Fix an upstream value at its source, then re-import it—never edit the snapshot in place.
- A complete thesis workspace for front matter, chapters, appendices, figures, tables, bibliography, institutional records, milestones, and durable open work.
- A generic, buildable LaTeX template for English and Simplified Chinese master's theses and doctoral dissertations, with the reusable class, authoring macros, and bibliography style separated from thesis content.
- A fingerprinted evidence layer under
mates/, importing selected artifacts from multiple STAR, STAGE, STORY, or structured generic repositories while preserving source paths, commits, import dates, and SHA-256 fingerprints. - A thesis-level source of truth under
notes/: the central argument, research arc, contribution map, publication/reuse map, chapter architecture, notation, style, reading notes, and claim ledger are created on demand by their owning workflows. - Degree-aware standards:
degree/profile.texselectsmasterordoctoral; level-specific synthesis, examination, defense, and deposit gates remain disabled while that fact is unknown. - Institutional facts kept separate from guesses: official requirements, title-page wording, committee records, templates, limits, approvals, and deadlines enter only from author-confirmed sources under
degree/andmiles/. - The full thesis lifecycle through sixteen skills: adoption, evidence curation, synthesis, outlining, chapter drafting, figures, tables, references, copy editing, audits, mock examination, feedback resolution, defense, deposit, and status reporting.
- Deterministic build and checks:
execs/run.shbuilds out of tree;lint.shchecks references, todos, degree-profile consistency, page limits, and formatting;fmt.shkeeps English prose at one sentence per line;import.sh --diffdetects evidence drift. - One workflow across seven agent harnesses: Codex, Claude Code, Cursor, DeepSeek Harness, Kimi Code, Pi, and Qwen Code share the same neutral skills and request router.
- Project-owned memory under
.story/memory/for durable session knowledge that no evidence, degree, note, milestone, or task file already owns. - Replies and notes in English or Simplified Chinese:
STORY_LANGsets the language a run replies and writes in, and this README and the skills guide also ship in Simplified Chinese, while paths, IDs, states, commands, and machine-readable fields remain stable in English.
See Writing workflow for each skill's responsibility and output. The STORY Workflow Skills Guide gives the compact pipeline; the Writing Workflow Conventions define the evidence, degree, milestone, language, and verification contracts every skill follows.
STORY/
├── manus/ # Thesis source
│ ├── main.tex # English entry point
│ ├── main-zh.tex # Buildable Simplified Chinese starter
│ ├── fronts/ # Abstract, acknowledgements, declarations
│ ├── chaps/ # Numbered chapters: <nn>_<slug>.tex
│ ├── backs/ # Appendices and other back matter: <letter>_<slug>.tex
│ ├── figs/ # Figure files <owner>_<slug>.tex; figs/srcs/ holds PDFs and editable sources
│ ├── tabs/ # Evidence-backed LaTeX tables: <owner>_<slug>.tex
│ ├── bibs/ # reference.bib (created on first use)
│ └── stys/ # story.cls, story.sty, story.bst
├── mates/ # Imported evidence snapshots—read-only
│ ├── <source-slug>/ # One namespaced source repository
│ ├── manual/ # Manually supplied research artifacts
│ └── MANIFEST.md # Provenance and SHA-256 ledger
├── degree/ # Author-confirmed institutional facts
│ ├── profile.tex # Degree level, language, title-page metadata
│ ├── requirements.md # Sourced degree and deposit checklist
│ └── committee.md # Confirmed supervision and committee record
├── notes/ # Thesis narrative and writing metadata
│ ├── story.md # Central argument and degree research arc
│ ├── contributions.md # Contribution → evidence/publication/chapter
│ ├── publications.md # Authorship, reuse, permissions, overlap
│ ├── outline.md # Chapter briefs and visual plans
│ ├── claims.md # Claim ledger
│ ├── notation.md # Thesis-wide notation
│ ├── style.md # Measurable prose conventions
│ └── refs/ # Reading notes and reference index
├── miles/ # Proposal, reviews, examination, defense, deposit
│ └── <slug>/ # milestone.yml, feedback/, simulations/, response/, materials/, template/, RECORD_*.md
├── tasks/ # Durable unresolved work and feedback promises
├── wkdrs/ # Builds and regenerable reports; gitignored
├── execs/
│ ├── run.sh # Thesis build entry point
│ ├── update.sh # Sync upstream workflow files; --adopt installs the skeleton
│ └── scpts/ # import.sh, lint.sh, fmt.sh
├── docs/ # Documentation site and workflow guides
├── .story/memory/ # Project memory; local/ is git-ignored
├── .agents/ # Neutral skills, shared /story router, /story-auto procedure
├── .codex/ # Codex hooks, manifests, and $story / $story-auto plugin
├── .claude/ .cursor/ .dsh/ # Harness-specific entry points and hooks
├── .kimi-code/ .pi/ .qwen/ # Harness-specific entry points and hooks
├── .env.example # Local configuration example
├── AGENTS.md # Shared rules for AI writing agents
└── README.md
The abbreviated directory names follow STAR and STAGE:
| Directory | Stands for | Contents |
|---|---|---|
manus/ |
Manuscript | The thesis's LaTeX sources |
fronts/ |
Front matter | Abstract, acknowledgements, declarations, and other preliminary material |
chaps/ |
Chapters | One <nn>_<slug>.tex file per thesis chapter, keyed in outline order |
backs/ |
Back matter | Appendices and other material after the main chapters, <letter>_<slug>.tex |
figs/ |
Figures | Figure files <owner>_<slug>.tex, with rendered graphics and editable sources (PDF, PPTX, …) under srcs/ |
tabs/ |
Tables | Evidence-backed tables <owner>_<slug>.tex |
bibs/ |
Bibliographies | The thesis bibliography |
stys/ |
Styles | Reusable class, package, and bibliography style |
mates/ |
Materials | Fingerprinted, read-only evidence snapshots |
miles/ |
Milestones | One directory per proposal, review, defense, correction round, or deposit attempt |
execs/ |
Executions | Build and update entry points; scpts/ holds utilities |
wkdrs/ |
Work directories | Builds and ephemeral reports, never durable project state |
mds/ |
Markdowns | Markdown documentation grouped by topic |
srcs/ |
Static sources | Documentation images and editable visual sources |
Files under chaps/, backs/, figs/, figs/srcs/, and tabs/ are named <key>_<slug>.<ext>: one underscore, then a lowercase slug whose words are joined by -, a Chinese twin ending in -zh. A chapter's key is its two-digit number and an appendix's a letter, while a figure file, its graphic or source, or a table takes <owner>, the key of the one chapter or appendix that includes it (00 for front matter, or 0 in a thesis that keeps one-digit chapter keys), with no number of its own; fronts/ stays unprefixed. With these names a directory lists in the same order in git and the terminal as in VS Code, Overleaf, and Finder, and lint.sh warns on a name off the scheme (§5 of the conventions).
Three rules matter more than the directory names. mates/ is read-only except through execs/scpts/import.sh and story-evid-curator; wkdrs/ is regenerable, so durable outcomes belong in notes/, miles/, or tasks/; and a fresh clone intentionally contains only notes/.gitkeep and notes/refs/.gitkeep. The workflow that owns a notes/*.md artifact creates it on first use—absence means “not initialized,” not “missing from the template.”
The template separates reusable typesetting from author-owned content and institutional facts:
| Layer | File | Owns |
|---|---|---|
| Thesis entry point | manus/main.tex or manus/main-zh.tex |
Front/chapter/back order, thesis-wide macros, bibliography activation |
| The look | manus/stys/story.cls |
Book layout, page geometry, title page, headings, localization, hyperlinks, citations |
| The authoring layer | manus/stys/story.sty |
\todo, reference helpers, table columns, and writing macros used by chapters and tables |
| Bibliography style | manus/stys/story.bst |
How bibliography entries are typeset |
| Degree facts | degree/profile.tex |
Degree level, thesis language, official title-page fields, confirmed page limit |
Project-specific commands such as \newcommand{\method}{...} belong in the entry point, not in story.cls or story.sty. The separation makes an institutional-format adaptation reviewable; an instance owns its entire manus/ tree, and execs/update.sh never replaces it.
The class accepts normal book options plus draft|final, en|english|zh|chinese, and cjk. The default is English draft mode. The included English entry point uses \documentclass[oneside]{stys/story}; the Chinese starter uses \documentclass[oneside,zh]{stys/story} and a % !TeX program = xelatex directive. cjk lets an English thesis typeset Chinese text: under XeLaTeX or LuaLaTeX it loads ctex with scheme=plain, which leaves the English headings and layout as they are; under pdfLaTeX the class stops with an error asking for % !TeX program = xelatex; with zh it has no effect.
manus/main.tex and manus/main-zh.tex share story.cls, story.sty, and one degree/profile.tex. Title-page fields use \storylocalized{English}{中文}, so each entry point selects the appropriate form without duplicating institutional metadata.
To try the Chinese starter locally:
STORY_MAIN=manus/main-zh.tex
LATEX_ENGINE=bash execs/run.sh
bash execs/scpts/lint.shWhen LATEX_ENGINE is empty, run.sh honors the entry point's TeX-program directive and therefore selects XeLaTeX for main-zh.tex; an explicit engine may be pdflatex, xelatex, or lualatex. Before making Chinese the canonical thesis language, confirm the institutional rule and set % dissertation_language: zh in degree/profile.tex. The class localizes the structure; it never translates thesis content or invents degree metadata.
When degree/requirements.md requires abstracts in both languages, each abstract names its language: \begin{storyabstract}[en] and \storykeywords[en]{...} in fronts/abstract.tex, [zh] in fronts/abstract-zh.tex. The argument defaults to the class language and sets the heading, the table-of-contents entry, and the keyword label: Abstract and Keywords: for en, 摘要 and 关键词: for zh. main-zh.tex carries a commented % \input{fronts/abstract} for an English abstract, which needs nothing more. main.tex carries a commented % \input{fronts/abstract-zh}; a Chinese abstract there also needs the cjk class option and XeLaTeX, so load the class as \documentclass[oneside,cjk]{stys/story} and change the first two lines to % !TeX program = xelatex and % !LW recipe = XeLaTeX. Built under XeLaTeX without cjk, Chinese text comes out blank while the build still succeeds, so lint warns when the build log reports missing characters.
Set exactly one author-confirmed degree mode in degree/profile.tex:
% degree_level: master
% or: degree_level: doctoralThe level is deliberately not an .env option: it is a durable institutional fact. Missing stays unknown. An invalid value, and wording in the \degree field that conflicts with the selected level, fail lint; the title is not checked, so an approved title may use a subject word such as “Doctor” or “Master”. % dissertation_language takes en or zh: lint warns while it is empty and fails on any other value. STORY applies only the selected level's contribution expectations and only those milestones the institution actually requires.
The bundled class is intentionally generic. Official university templates, title-page wording, margins, front-matter order, page limits, deadlines, submission portals, embargo choices, and approval rules must come from official material confirmed by the author. Record the canonical profile in degree/profile.tex, the sourced checklist in degree/requirements.md, and milestone-specific rules in miles/<slug>/milestone.yml. The title page's submission statement, printed above the degree name, is one of those profile fields: set \submissionstatement{...} to the official template's exact wording, or to \submissionstatement{} when the template prints none, which drops the line. Until then the title page prints the placeholder Submission Statement (提交说明 in Chinese), which lint reports with the other title-page placeholders; lint also warns when a profile has no \submissionstatement line at all. Keep an official template you were given, unchanged, under miles/<slug>/template/, which fmt.sh never reformats; a class the thesis actually builds with belongs in manus/stys/. Do not silently rewrite STORY's generic source tree from memory.
Use this repository as a GitHub template, or clone it and detach the copy—one degree thesis, one repository:
git clone https://github.com/wanghao9610/STORY
cd STORY
rm -rf .git
rm -rf .github # Upstream maintainer CI; it checks STORY's generated harness mirrors.
cd ..
mv STORY YOUR_THESIS_NAME
cd YOUR_THESIS_NAME
git init
git add .
git commit -m "First commit."If you use GitHub's Use this template action, the new repository already has its own Git history; remove .github/ unless you intend to maintain a fork of STORY itself. The upstream workflow checks STORY's seven generated skill trees and documentation, not the contents of an individual thesis.
If a draft is already underway—an Overleaf export, a working LaTeX tree, years of chapters, or results already in the text—install the STORY skeleton into that repository instead of moving it into a fresh clone. Run at the existing repository root:
curl -fsSL https://raw.githubusercontent.com/wanghao9610/STORY/main/execs/update.sh -o /tmp/story-update.sh
bash /tmp/story-update.sh --adoptAdoption never overwrites an existing path: it copies only absent files and reports what it keeps. Add --harnesses claude—or a comma-separated set of claude, codex, cursor, dsh, kimi, pi, and qwen—to install only the agent trees you use. Then invoke story-proj-adopt; it inventories the draft, asks you to confirm the degree level before mapping level-specific material, has you commit first and records that commit, asks before the file map or entry point changes, copies the original sources rather than moving them, records existing unsourced statements as audit work, and verifies the resulting build. It does not fill degree/requirements.md or the rest of the profile: you do. A draft built on an institutional class keeps that class in manus/stys/; lint checks the zh class option against % dissertation_language only when the entry point loads STORY's class, and for any other class it logs that the language option is not checked, without a warning.
Copy the local configuration:
cp .env.example .env# Optional default evidence repository; --source imports additional repositories.
RESEARCH_HOME=
# Default thesis entry point, relative to the repository root.
STORY_MAIN=manus/main.tex
# pdflatex | xelatex | lualatex; empty honors the entry point, then uses pdflatex.
LATEX_ENGINE=
# Upstream template and harness trees maintained by execs/update.sh.
STORY_REPOSITORY=https://github.com/wanghao9610/STORY.git
STORY_HARNESSES=all
# Workflow interaction and Markdown/reply language.
INVOLVE=medium
STORY_LANG=.env is ignored by Git. STORY_MAIN selects the default entry point for both build and lint, while --main overrides it for one command. INVOLVE=low|medium|high sets how much unresolved judgment a skill asks about under the authority you already gave: low takes the recommended safe option and says so, medium asks as each skill documents, and high asks each consequential choice on its own. Approval you already gave stays valid for its scope and is not asked for again, and a status, audit, or mock-review request ends with its own report and never starts a writing skill after it. No level skips a confirmation point — recording an institutional, requirement, or milestone fact as confirmed, deleting a file or ledger row, replacing a file wholesale, or freezing or tagging a deposit (conventions §7) — or an ask-first choice of AGENTS.md §1: the thesis-wide argument, chapter boundaries, attribution, publication reuse, or a degree requirement. It is the project default, and an involve=<level> token in a single invocation overrides it for that run. In Claude Code the token also reaches the permission hooks, which read it off the most recent STORY command you typed and keep it after the run ends, until you type the next one; elsewhere the prompts follow .env alone. At low, the permission hooks also skip the harness's prompt before an edit inside the project and, in Claude Code, before a shell command outside the red lines; writes into mates/, degree/, and miles/*/feedback/ keep the prompt at every level (Hooks and permissions). STORY_LANG=en|zh controls replies and newly written Markdown unless you ask for a language in the conversation; empty follows the language of your own messages (a run with none asks once), and an existing file is never translated. Text for examiners, the committee, or the institution uses the language the milestone or degree/requirements.md records, else the manuscript language, and the run asks before finalizing it. The manuscript language and degree level remain in degree/profile.tex.
Next, fill degree/profile.tex, degree/requirements.md, and degree/committee.md only from official material or records the author has confirmed. Unknown values stay empty; do not infer a degree level from the thesis title or degree name.
Import each source under a stable slug:
bash execs/scpts/import.sh --source ../my-star-project --slug project-a
bash execs/scpts/import.sh --source ../my-stage-paper --slug paper-a
bash execs/scpts/import.sh --source ../earlier-story --slug prior-thesisimport.sh recognizes STAR, STAGE, STORY, and structured generic repositories; it selects writing-relevant artifacts, copies them under mates/<slug>/, and records source type, absolute source path, source commit, SHA-256 fingerprint, import date, and coverage in mates/MANIFEST.md; a re-import rewrites each entry but keeps a covers: line you curated. If --source is omitted, it uses RESEARCH_HOME. Re-run after upstream work changes, or check without writing:
bash execs/scpts/import.sh --diff --source ../my-star-project --slug project-aThe diff prints one line per file that differs: stale for a snapshotted file whose source changed, new upstream for a source file with no snapshot under mates/<slug>/, and removed upstream for a manifest entry whose source file is gone. It exits 2 when it prints a stale or new upstream line, 0 otherwise, and 1 when the check itself cannot run. Only a file with a stale line is stale, and a stale snapshot is not registered evidence until you re-import it. A removed upstream line is reported for you to decide on; the snapshot stays, since a re-import never deletes one. Imported evidence flows one way: correct it upstream and re-import it.
If the thesis has no STAR or STAGE source repository, keep supplied results, reports, tables, or other research artifacts at their source path and invoke story-evid-curator register path=<file>; one run can register a batch. The curator records their origin, owner, date, and coverage before copying them into mates/manual/ and fingerprinting them in mates/MANIFEST.md. A file without a manifest entry is not evidence. A corrected artifact becomes a new registered record; it is never silently edited in place.
Both paths can be mixed. Multiple research projects, published papers, collaboration records, and manual evidence drops may feed the same thesis as long as each source is namespaced and its authorship boundary remains explicit.
bash execs/run.sh
bash execs/scpts/lint.sh
bash execs/scpts/fmt.sh --checkrun.sh invokes latexmk, builds out of tree under wkdrs/builds/ (an entry point outside manus/, such as a defense deck, builds into a git-ignored .build/ beside it), and prints the PDF path and page count when pdfinfo is available. lint.sh builds by default, then fails on a failed build, undefined citations or references, visible \todo markers (read as TeX reads the source, so a marker whose argument a comment or line break splits still counts), a .tex file or directory under manus/, the entry point, or degree/profile.tex that it cannot read, or a .tex file under manus/ saved as UTF-16 or UTF-32, whose markers go uncounted, invalid or conflicting degree metadata, and a confirmed page-limit overrun. The limit is the active milestone's max_pages (the one non-supervision milestone with status: active). When there is none, it is the max_pages of the milestone the legacy active_milestone in notes/story.md names, and otherwise the value in degree/profile.tex; lint compares it with the PDF's total page count, which it reads with pdfinfo or, without it, from the build log's Output written on line, and it warns that the limit was not checked when neither gives a count. It warns about title-page placeholders (a profile with no \submissionstatement line included), an unset % dissertation_language, an entry point that loads STORY's class with a language option, or without one, that disagrees with it, unresolved rows in degree/requirements.md, a chapter file the entry point never inputs, a manuscript file name off the owner-key scheme, more than one active milestone, a max_pages that is not a positive integer, a milestone record, degree/requirements.md, or notes/story.md it cannot read, a source or record that is not valid UTF-8 (read byte by byte, and a manuscript file's prose left unreviewed), sources newer than the PDF, overfull boxes, missing characters in the build log, formatting drift, an unknown degree level, high-confidence chatbot residue, and clustered formulaic prose. The requirement count covers only unchecked boxes; whether a checked row cites its source is still read by story-depo-packer, and §6 of the conventions (Deposit gates) says which warnings block a deposit. Prose findings are advisory review signals, not proof of AI authorship and not hard failures. Every run ends with a Result: line, a failed build included. A red lint result is the expected state of a mid-draft manuscript — the \todo markers the evidence contract requires you to write are themselves hard failures until resolved, and they block only deposit, not drafting. --no-build reuses the last build: it fails when that build's log is missing or stopped on an error, and warns when a source is newer than the PDF.
fmt.sh uses the repository's latexindent configuration to preserve one sentence per line without changing typeset text. It keeps a closing } or ] on the line of the sentence it ends, and it refuses any rewrite that would change the typeset text, leaving that file untouched and exiting 2. A refused file needs a hand fix: usually a closing } or ] alone on its line, which goes at the end of the line above in place of the bare % that ends it, if there is one (that % only ate the line end, and the closer keeps a % after it only if its own line ended in one); a {% group around running prose (\mbox{% … }), which goes on one line without the %; or a sentence that follows a closing } on its line (\todo{...} The end., \emph{One thing.} here. The end.), which goes on a line of its own. A period glued to a footnote, citation, label, index entry, or \todo (good.\footnote{...}, et al.\cite{x}) ends a sentence only after the command, and one before an escaped or thin space (et al.\ The, Fig.\,3) ends none, so neither is split where the source has no space. An abbreviation read as a sentence end before a capital or a number (et al. The, Fig. 3) is not refused but split onto two lines, since a line break is a space; a tie keeps the sentence whole. It does not yet split or check Chinese sentences, so keep one sentence per line by hand in Chinese prose; --check passes a multi-sentence Chinese line. It excludes reusable styles (manus/stys/) and official institutional templates (miles/*/template/). Run it without --check to apply formatting.
The repository structure and scripts work without an AI harness. When using the workflow skills, start from the state that describes the thesis:
| Current state | Start with |
|---|---|
| Existing draft or Overleaf export | story-proj-adopt |
| Fresh repository with source research ready | story-evid-curator |
| Evidence registered, thesis argument still unclear | story-syns-coach |
| Argument and contributions confirmed, chapters not planned | story-outl-planner |
| Unsure what is initialized or blocked | story-flow-status |
The exact command prefix depends on the harness: $story-* in Codex, /story-* in Claude Code, Cursor, Pi, and Qwen Code, and /skill:story-* in DSH and Kimi Code. The generic $story or /story router accepts a plain-language request and selects one workflow; six thesis-wide or milestone workflows require explicit invocation. /story-auto <goal> ($story-auto in Codex) pursues a stated goal across several steps, starting the ten unmarked skills itself and stopping at any † skill or author decision.
The sixteen skills form a pipeline, not a rigid sequence. Use the smallest skill that owns the artifact in question. Every skill first loads the shared workflow conventions.
After every skill finishes, its report closes with exactly one Next action: handoff: the owning skill and concrete target or command for the earliest remaining gate in the pipeline order of §8 of the conventions (Completion handoff), an author action when only the author can clear it, or Next action: none — the requested workflow is complete. The handoff recommends what to do next; it does not silently start another skill.
| Skill | Use it when | Primary output |
|---|---|---|
story-proj-adopt † |
An existing thesis or Overleaf export must enter STORY safely | notes/adopt.md, copied and mapped sources, unsourced-claim backlog |
story-evid-curator |
Evidence must be imported, registered, refreshed, or integrity-checked | mates/, mates/MANIFEST.md |
story-syns-coach † |
The thesis problem, central argument, questions, research arc, or contributions need confirmation | notes/story.md, contributions.md, publications.md, claims.md |
story-outl-planner † |
The confirmed thesis story must become a chapter architecture | notes/outline.md with chapter briefs, notation.md, scaffolds for chapters that have no file |
story-chap-drafter |
One chapter, or one front- or back-matter file, needs evidence-bound drafting or revision in the author's scholarly voice; trace adds missing source anchors without redrafting |
One manus/chaps/, manus/fronts/, or manus/backs/ file and synchronized ledgers |
story-tabs-builder |
One result, comparison, mapping, or synthesis table is needed | One manus/tabs/<owner>_<slug>.tex file with a source anchor on every row that carries a number or comparison |
story-figs-designer |
One conceptual, method, result, or synthesis figure is needed | Figure file manus/figs/<owner>_<slug>.tex plus its rendered graphic and editable sources under manus/figs/srcs/ |
story-refs-curator |
A source must be added, verified, read, deduplicated, or positioned | Bibliography entries and notes/refs/ reading notes |
story-copy-editor |
Authorial voice, formulaic prose, terminology, transitions, repetition, or notation need polishing in one chapter, one front- or back-matter file, or the whole thesis (full) |
Manuscript edits, report, advisory tasks/prose.md, or notes/style.md |
story-clms-auditor |
Numbers, comparisons, and degree-contribution claims need traceability checks, or a number looks wrong | Claim and contribution statuses, a regenerable report, lines in tasks/audits.md |
story-cite-auditor |
Citation keys, literature assertions, and bibliography hygiene need checking | Citation report and lines in tasks/audits.md |
story-exam-reviewer |
A degree-appropriate mock examiner or committee review is needed | miles/<slug>/simulations/SIM_EXAM_<date>.md, or wkdrs/reports/SIM_EXAM_<date>.md when no milestone is named or active |
story-revs-resolver † |
Supervisor, committee, examiner, defense, correction, or deposit feedback, or an official outcome, arrived | Point ledger, responses, promises in tasks/<slug>_promises.md, an outcome's RECORD |
story-defn-builder † |
An applicable pre-defense or defense narrative and deck are needed | Defense plan and editable deck sources under miles/<slug>/materials/ |
story-depo-packer † |
A named deposit milestone is ready for preflight and freeze | Gate report, deposit bundle, a RECORD with checksums and the source commit, optional local freeze tag |
story-flow-status |
The next action is unclear | Read-only status report and exactly one next action |
The slugs abbreviate: proj project, evid evidence, syns synthesis, outl outline, chap chapter, tabs tables, figs figures, refs references, clms claims, cite citations, exam examination, revs reviews, defn defense, depo deposit, flow workflow.
The six skills marked † control thesis-wide argument, chapter boundaries, institutional milestones, or finalization. The generic router never starts one; it returns the exact command for you to type, and a /story-auto goal run stops at one and prints its command. This boundary keeps an agent from silently changing the thesis's central claim, structure, response position, defense, or deposit state.
Chapter drafting, copy-editing, mock examination, and lint share the human-writing contract in §5 of the workflow conventions. It adapts Humanizer patterns to academic prose while preserving evidence, qualifications, terminology, and author-confirmed voice; it does not classify authorship from isolated words or punctuation.
The common path is:
- Establish the instance — clone STORY or run
update.sh --adopt; confirmdegree/profile.texfrom official records. - Curate evidence — import each STAR, STAGE, STORY, or generic repository and register manual artifacts; every evidence file receives a fingerprint.
- Shape the thesis —
story-syns-coachturns the research history into one degree-level problem, central argument, research arc, questions, contributions, publication/reuse map, and proposed claims. - Plan the chapters — once the author finalizes the story,
story-outl-plannermaps every chapter, drafted ones included, to its purpose, questions, contributions, claims, evidence, visuals, dependencies, and exit condition. - Build the literature base —
story-refs-curatorverifies bibliographic identity, reads claim-bearing sources, and creates checkable notes undernotes/refs/. - Draft one chapter at a time —
story-chap-drafterwrites from the confirmed brief and evidence;story-tabs-builderandstory-figs-designercreate traceable visuals. Claim, notation, and outline records change in the same edit. - Polish without moving the facts —
story-copy-editorremoves clustered formulaic prose and harmonizes terminology, authorial voice, transitions, and cross-chapter synthesis while preserving numbers, citations, attribution, uncertainty, and claim scope. - Audit —
story-clms-auditortraces numbers and contribution claims;story-cite-auditorchecks citation keys and literature assertions. Failures become open lines intasks/audits.mdrather than disappearing in a report, and each audit records the date of its last full run. - Examine and revise —
story-exam-reviewersimulates the applicable degree-level examination; received feedback remains immutable underfeedback/;story-revs-resolverrecords a disposition and completion evidence for every point, records an official outcome, and asks before opening a correction milestone. - Prepare the defense — when the confirmed program requires it,
story-defn-buildercreates the narrative and editable deck from verified claims and confirmed timing and format rules. - Pack and freeze the deposit —
story-depo-packerchecks every gate in §6 of the conventions (Deposit gates), among them a clean build and lint, every requirement row checked, no open box undertasks/, both audits run after the last change, cleared reuse, no starter text, and a clean Git tree, before producing the local bundle and a RECORD that cites it by checksum. It never commits, uploads, or submits on the author's behalf, and it tags the recorded commit only when you confirm.
story-flow-status can be run at any point. It reads the degree profile, evidence integrity (ok, tampered, missing, unregistered), status counts from each ledger, publication attribution, the active milestone, open boxes under tasks/, the visible \todo count, whether the build is current, the latest lint Result: line, and any legacy translated twins, then recommends exactly one next action.
Three ledgers keep the thesis defensible:
A. Evidence flows one way. A file becomes evidence only when mates/MANIFEST.md records a matching fingerprint and provenance:
## project-a/wkdrs/results/results.md
- source-type: star
- source: /path/to/project-a/wkdrs/results/results.md
- source-commit: 3f2a91c
- sha256: 8a31...
- imported: 2026-08-23
- covers: imported graduate-research evidenceEvery quantitative or comparative sentence in manus/ then has either a nearby source anchor or a claim-ledger evidence link:
% src: mates/project-a/wkdrs/results/results.md#main-comparison
The proposed method improves the confirmed metric by ... .If support is missing, write \todo{...}. Remembered, interpolated, or plausible-looking values are not a third option.
B. The claim ledger is the hub. notes/claims.md uses ID | Claim | Contribution | Stated in | Evidence | Status | Notes. Claim IDs are stable (C001, C002, …); their lifecycle is proposed → drafted → verified, with unsourced, weakened, and retired preserving failures and decisions instead of erasing history. The synthesis proposes claims, chapters state them, audits verify them, and reviews attack the same rows.
C. Attribution is separate from evidence. notes/contributions.md maps degree contributions (D001, D002, …) to research questions, claims, evidence, publications, chapters, and attribution. notes/publications.md separately records complete authorship, the candidate's contribution, reused material, overlap, and permission or policy status. A publication is not automatically a degree contribution, and fingerprinted evidence never licenses STORY to imply sole authorship of collaborative work.
Assertions about cited work follow the same boundary: metadata verification proves which paper it is; content verification means the source itself was read and notes/refs/ supports the assertion. Public availability never implies reuse permission.
Each applicable proposal, review, annual review, pre-defense, external examination, defense, correction round, deposit, or institution-specific event gets one miles/<slug>/ directory. STORY never creates a milestone merely because another institution or degree level uses it.
miles/<slug>/
├── milestone.yml # Confirmed kind, status, due date, source, and limits
├── feedback/ # Received comments, preserved unchanged
├── simulations/ # Generated mock reviews (story-exam-reviewer)
├── response/ # Point ledgers, dispositions, and completion evidence
├── materials/ # Applicable proposal, examination, or defense artifacts
├── template/ # Official template as supplied, never reformatted
└── RECORD_<date>.md # Frozen outcome; required before status: completed
milestone.yml accepts proposal, review, annual-review, pre-defense, external-examination, defense, correction, deposit, supervision, or other, with status planned, active, blocked, completed, or cancelled. supervision is the standing miles/supervision/ record for informal supervisor or coauthor feedback: it is never the active milestone, needs no RECORD, and gates only its own promises. Dates, page limits, official names, and requirements sources remain empty until confirmed.
Received feedback is never edited in place. A response records each point as accepted, completed, planned, disagreed, or needs-author, and promised changes also become checkboxes under tasks/. A deposit is ready only when story-depo-packer reports every gate of §6 of the conventions (Deposit gates) as passing.
The harness trees share one source of truth. Neutral skills live under .agents/skills/; the shared request roster lives under .agents/commands/story.md and the goal-run procedure beside it in story-auto.md; each harness owns only the frontmatter, prompts, hooks, settings, and command adapters its runtime requires.
| Harness | Skill entry | Project setup |
|---|---|---|
| Codex | $story-*; generic $story and $story-auto plugin |
Approve .codex/hooks.json with /hooks; install the plugin below |
| Claude Code | /story-*; generic /story and /story-auto |
.claude/settings.json loads automatically |
| Cursor | /story-*; generic /story and /story-auto |
.cursor/hooks.json and rules load automatically |
| DeepSeek Harness | /skill:story-*; generic /story and /story-auto |
Install .dsh/commands/story; run bash .dsh/hooks/install.sh once per machine |
| Kimi Code | /skill:story-*; generic /story and /story-auto |
Install .kimi-code/plugins/story; run bash .kimi-code/hooks/install.sh once per machine |
| Pi | /story-* prompts; generic /story and /story-auto |
Trust the project so .pi/extensions/ can load |
| Qwen Code | /story-*; generic /story and /story-auto |
.qwen/settings.json loads automatically |
Install the repository-local Codex router once from the repository root, then start a new session:
codex plugin marketplace add .
codex plugin add story@storyFor Kimi Code, run in its prompt from the repository root; /new may replace /reload:
/plugins install ./.kimi-code/plugins/story
/reload
For DSH, install the command bundle into each profile and restart that profile:
dsh plugin --profile YOUR_PROFILE add ./.dsh/commands/story
dsh --profile YOUR_PROFILE --dump-configUse $story or /story with no request for thesis status, or pass a plain-language request such as audit the claims in chapter 3. All wrappers route from the same roster.
Use /story-auto <goal> ($story-auto in Codex; /skill:story-auto is Kimi Code's explicit spelling) when you want the agent to keep going toward a goal, such as /story-auto chapter 3 drafted and audited involve=low. It runs story-flow-status, then the next action each run names, starting the ten unmarked skills itself until the goal's check passes. It stops and hands back the exact command at any † skill, and the author action at any gate only you can clear. Confirmation points and the ask-first choices of AGENTS.md §1 still come to you at every involve level. A goal run never imports or refreshes evidence, writes degree/ or received feedback, declares a deposit ready, commits, or pushes, and it does not wait for green lint. Its level is the involve= token you type, else INVOLVE in .env. The rule is §8 of the workflow conventions (Goal runs); every harness reads the same procedure, .agents/commands/story-auto.md. Codex and Kimi Code copy the plugin when it is installed, so an existing install picks up /story-auto, and any later change to the plugin, only once you install it again. In Codex, run codex plugin remove story@story, then codex plugin add story@story, and start a new session; in Kimi Code, repeat the plugin install above.
Claude Code runs story-flow-status at effort: medium: its generated .claude/skills/story-flow-status/SKILL.md carries that field, because a read-only status scan needs less reasoning depth than drafting. No other skill, and no other harness, carries a model or effort setting; which model runs a skill, and how deeply it reasons, is your harness's choice.
Maintainers of STORY itself edit neutral content under .agents/skills/ and .agents/commands/, then run bash .github/scripts/port.sh --write; thesis instances normally receive those files through execs/update.sh instead.
Two hooks run at the start of a session in every harness: one states the model id to copy into a memory file's model_id (the recovery order is §7 of the workflow conventions; each harness's resolver command, fallback read, hook events, and registration are in §11, harness adapters), the other puts the project memory index in front of the agent. All seven harnesses also carry story_commit_guard.sh, at every involve level: it declines blanket or forced staging, history rewrites, forced branch operations, blanket discards of uncommitted work, forced pushes (a +refspec included), deleting a remote branch or tag (push -d, --delete, --prune, or a :dst refspec), moving or deleting a tag (update-ref on refs/tags/ or with --stdin included), and a commit whose staged files exceed 10 MB. Claude Code, Codex, DSH, Kimi Code and Qwen Code run it before a shell command on PreToolUse, Cursor on beforeShellExecution, and Pi on its tool_call event, where it is the only check between a git command and the repository, since Pi has no permission prompts.
At INVOLVE=low the gate hooks answer permission prompts. They never answer a confirmation point: the questions a skill must ask still reach you. In Claude Code, Codex and Qwen Code, story_involve_gate.sh allows an edit inside the project. Paths under a dot-directory at the project root, and paths that climb out through .., keep their prompt. Claude Code also registers story_bash_gate.sh, which allows a shell command at low unless it crosses a red line: deletion, sudo, disk and device writes, system or TeX package installs (tlmgr included), process control, service control, kernel modules, scheduled jobs (crontab), a find that deletes or executes, git push, git clean, git stash drop/clear, a whole-tree git restore/checkout, a forced mv/cp, or an outward transfer (gh, scp/sftp/ftp, rclone, rsync to a host, or a curl/wget upload; a plain download stays allowed). Both gates keep the prompt for a write into the thesis's protected records at every level: the evidence store mates/, the confirmed institutional facts in degree/, and received feedback in miles/*/feedback/. The bash gate lets bash execs/scpts/import.sh write into mates/, which is its job, and lets read-only commands such as cat, grep and sed -n read there. story-evid-curator's own registration therefore asks you before it copies a file into mates/manual/. In Claude Code, both gates take the level from the involve= token of the session's most recent STORY command you typed, falling back to .env when that command names none. A token the agent writes into a skill it dispatches can raise the level, but never lower it. That level outlasts the run: after /story-chap-drafter 3 involve=low finishes, later edits and shell commands in the same session are still answered at low, and a plain-language request such as "ask me more" changes what a skill asks but not what the hooks answer. Type a bare STORY command, such as /story-flow-status, to return the hooks to .env, or one carrying a new involve= token to set another level. Codex and Qwen Code follow .env alone. Cursor, DSH, Kimi Code and Pi have no edit gate, because their harnesses offer no prompt a hook can answer before an edit.
The gates only read the paths a command names, so they are a floor, not a proof. A script that opens a protected file on its own is not seen, and the conventions still forbid that write.
Claude Code needs nothing else on a fresh install: .claude/settings.json ships three allow rules, one for the read-only model-id resolver the provenance hook hands a skill and two for story-flow-status's read-only collector. execs/update.sh keeps an existing settings.json; it names any STORY hook a kept file does not register and reports a missing resolver rule. Merge the rules into a kept file yourself:
"permissions": {
"allow": [
"Bash(bash .claude/hooks/story_model_id.sh --resolve:*)",
"Bash(bash .claude/skills/story-flow-status/scripts/scan.sh)",
"Bash(bash .claude/skills/story-flow-status/scripts/scan.sh:*)"
]
}A kept file also needs the story_bash_gate.sh command beside story_commit_guard.sh in the Bash entry under hooks.PreToolUse; the guard's deny outranks the gate's allow, so the order does not matter. Qwen Code's .qwen/settings.json ships its own scan.sh rules. Elsewhere, approve the collector once when asked.
What a session learns that no repository file owns—a machine-specific TeX limitation, a standing author preference, a reusable project judgment, or a framing already tried and rejected—may live under .story/memory/. Each fact lives in its own file; a session hook builds a one-line-per-fact index from those files' frontmatter and puts it in front of the agent at every session start, in all seven harnesses (--list on any copy prints it, for example bash .claude/hooks/story_memory.sh --list).
Four types keep the store legible: env, pref, insight, and deadend. .story/memory/local/, git-ignored like .env, holds what is true only of this machine and anything you would rather keep off the repository; every other memory is versioned and travels with a clone. An env fact older than 180 days is marked stale. A memory is never evidence and cannot override a file that already owns the fact: values belong to mates/, claims to notes/claims.md, institutional requirements to degree/, publication reuse to notes/publications.md, feedback to miles/, and promises to tasks/.
The agent offers before recording memory; INVOLVE=low changes that to record-and-tell. The file format (including the required one-line summary), the index line, and retirement rules are in §10 (project memory) of the workflow conventions; a memory's model_id follows the provenance rule in §7.
An instance can sync later STORY workflow releases without changing its manuscript, evidence, degree records, notes, milestones, tasks, memory store, Git branch, or remotes:
bash execs/update.shThe updater manages shared agent instructions, neutral skills, the /story router and /story-auto procedure, selected harness entry trees and hooks, Codex manifests, router packages, workflow documentation, and every script under execs/. Harness registration files are installed when absent and otherwise kept unless --force is supplied. When a kept file does not register a STORY hook, the updater names the hook, and it reports a kept .claude/settings.json that does not allow the model-id resolver. Merge those entries from upstream by hand. It also reports a kept .codex/hooks.json whose story_memory.sh entry still shares a SessionStart group that has a matcher (startup|resume in earlier releases); move that entry into a SessionStart group of its own with no matcher, as upstream does, so memory also loads after /clear. Instance-owned thesis state stays outside the update set.
The general forms are:
bash execs/update.sh [--diff] [ref] [--harnesses LIST] [--skill NAME] [--force]
bash execs/update.sh [ref] [--harnesses LIST] --adopt
Common examples:
bash execs/update.sh --diff
bash execs/update.sh TAG_OR_BRANCH
bash execs/update.sh --harnesses claude,pi
bash execs/update.sh --skill story-chap-drafter
bash execs/update.sh --skill story-flow-status--diffpreviews without writing and exits2when an update is available,0when everything matches, and1on error.- A
refpins the update to a branch or tag. --harnessesselects any comma-separated set ofclaude,codex,cursor,dsh,kimi,pi, andqwen;allis the default andnoneupdates shared paths only.--skillupdates only one skill across the neutral source, selected harness trees, Codex manifest, and Pi prompt.--forcepermits managed local changes and kept harness configurations to be overwritten without widening the path set.--adoptcopies absent skeleton files into an existing Git repository and never overwrites an existing path; it cannot be combined with--force.
The source is STORY_REPOSITORY, resolved from the environment, then .env, then the official GitHub repository. Matching managed files are overwritten and new upstream files are added. An update deletes nothing: a file that exists only locally, your own included, is kept, and --diff lists one under a managed path as extra. STORY no longer ships its Chinese instruction twins (a SKILL_zh.md beside each skill, AGENTS.zh-CN.md, CLAUDE.zh-CN.md, .pi/APPEND_SYSTEM.zh-CN.md, the Chinese /story router (.agents/commands/story.zh-CN.md), its wrappers, and Pi prompts, and the Chinese workflow specs) or the three standalone workflow specs (the human-writing guide, the memory spec, and the model-id fallbacks), whose rules now live in the workflow conventions (§5, §10, and §7 with §11). An update leaves in place any of these files a thesis still has, and no skill reads them, so delete them by hand. The notes/**/*.zh-CN.md twins earlier skills wrote beside your notes are yours: an update keeps them, no skill reads or updates them any more, and story-flow-status lists them so you can fold them in or delete them. An updater from before STORY dropped those files stops with Upstream ref is missing AGENTS.zh-CN.md before it can replace itself. Replace it once by hand with execs/update.sh from the repository you update from (STORY_REPOSITORY; for the official one, curl -fsSL https://raw.githubusercontent.com/wanghao9610/STORY/main/execs/update.sh -o execs/update.sh), commit the replacement so the updater's uncommitted-changes check passes, and run it again. An older release also seeded .story/memory/MEMORY.md and .story/memory/MEMORY.zh-CN.md, read .story/memory/local/MEMORY.md as the machine-local index, and paired every memory file with a <slug>.zh-CN.md twin. The memory store is the thesis's, so the update keeps all of them, but the hooks no longer read the index files and now list each twin as a second memory. Carry each index line into its memory file's summary, fold each twin into its English file, then delete the old files; the update reports them until you do. Milestone records now live under miles/ rather than milestones/: the update moves nothing, and reports a leftover milestones/ until you run git mv milestones miles and commit it. Manuscript file names now follow the owner-key scheme of conventions §5, and an update never syncs manus/, so it renames nothing there: rename an existing thesis's files by hand as the 2026-09-26 change-log entry lists, and lint.sh warns on each name off the scheme until you do. Commit current work before updating, preview when unsure, and review the result with git status and git diff. bash execs/update.sh --help is the authoritative flag reference.
- Record the canonical degree level and manuscript language in
degree/profile.tex, not.env; unknown institutional facts remain empty. - Keep thesis prose in the language selected by the degree profile. Keep structural paths, keys, IDs, and statuses in English.
- Treat
notes/story.mdas the thesis-level argument,notes/outline.mdas chapter ownership, andnotes/claims.mdas the claim ledger. Update them in the same change as the manuscript facts they govern. - Put every quantitative or comparative manuscript statement behind a nearby
% src:anchor or claim-ledger evidence link. Use\todo{...}when evidence is missing. - Never edit imported evidence in place. Correct it at the source and re-import it, or register a corrected manual artifact as a new record.
- Record publication authorship, candidate contribution, reuse, overlap, permission, and policy separately from evidence traceability.
- Keep received feedback unchanged. Put interpretations, dispositions, promises, and completion evidence beside it, not inside it.
- Build only with
bash execs/run.sh; keep generated outputs underwkdrs/; run lint whenever citations, claims, metadata, page limits, milestones, or finalization state may have changed. - Use one sentence per line in manuscript sources so a diff shows the sentence that changed rather than the paragraph around it.
- Make the smallest workflow own each change. A chapter drafting request does not silently alter evidence, degree requirements, thesis-wide argument, or received feedback.
The complete collaboration rules are in AGENTS.md; the authoritative workflow rules are in the Writing Workflow Conventions. Both are English only; a run in Chinese follows them and replies in Chinese.
When starting a real thesis instance:
- Replace the placeholders in
degree/profile.texonly with official, author-confirmed values and complete the sourced checklists underdegree/. - Choose one canonical entry point and make
STORY_MAIN,% dissertation_language, and the thesis sources agree. - Import each research or paper repository under a stable slug; register manual artifacts rather than dropping untracked evidence into the manuscript.
- Run
story-syns-coachbefore committing to chapter boundaries. A publication-based structure, synthesis chapter, defense, or milestone applies only when the confirmed degree and institution require it. - Keep reusable class/package files separate from project-specific macros and any official institutional template.
- Set
STORY_HARNESSESto the tools the project actually uses so later updates do not reinstall unwanted harness trees. - Replace the generic README and documentation landing page with the thesis's identity if the instance will be public, while keeping
docs/mds/story-workflow/available for the workflow. - Remove upstream maintainer CI from the instance unless it intentionally remains a STORY fork.
The skeleton is meant to carry the thesis's provenance and decisions, not dictate its scholarly argument or institutional format.
- Git 2.25+ and Bash 3.2+
- A reasonably complete TeX Live or MacTeX installation with
latexmk latexindentfor manuscript formatting- CTeX plus XeLaTeX or LuaLaTeX for the Simplified Chinese template and for a Chinese abstract under the
cjkoption pdfinfofor page counts:run.shreports one only with it, and lint otherwise reads the build log and warns when neither gives a counttexcountfor optional word countscurlfor adoption and upstream updatesshasumorsha256sumfor evidence fingerprints
Individual agent harnesses may add their own runtime requirements; DSH's local router installation, for example, requires pnpm on PATH.
Highlights, newest first. STORY does not tag releases yet, so bash execs/update.sh follows main; once a release is tagged, passing the tag as ref pins an update to it.
- 2026-10-09 — A figure is now a LaTeX file,
manus/figs/<owner>_<slug>.tex, holding the figure environment, caption, and label with either the drawing itself (TikZ, pgfplots) or\includegraphics{figs/srcs/<owner>_<slug>}, and its owner includes it with\input{figs/<owner>_<slug>}, as it includes a table. Every non-LaTeX file — the rendered PDF, PPTX, SVG, plotting script, evidence map — lives undermanus/figs/srcs/with the figure file's key and slug (§5 of the conventions, Manuscript file names).story-figs-designerwrites both, andstory-outl-plannermoves both on a renumber.lint.shnow warns on any file undermanus/figs/other than<owner>_<slug>.tex, and on a figure file whose graphic underfigs/srcs/has another name; a bare\includegraphicsname counts asfigs/srcs/when a\graphicspathlists it. An update does not move manuscript files, so in an existing thesisgit mveachmanus/figs/<owner>_<slug>.pdfintomanus/figs/srcs/, move its figure environment into a newmanus/figs/<owner>_<slug>.tex, and replace it in the chapter with\input{figs/<owner>_<slug>}.lint.shalso now asks Perl's strict decoder first whether a source is UTF-8: the macOS 26iconvrejects valid text once a few hundred multibyte characters run together, so lint called a Chinese chapter "not valid UTF-8" and skipped its prose review. - 2026-10-08 — LaTeX Workshop now builds through
bash execs/run.sh, so the editor and the command line use the same engine and the sameTEXINPUTS. Before, the% !TeX programline in an entry point outranked its% !LW recipeline and ran the bare engine withoutmanus/stys/onTEXINPUTS, so a class there that loads a sibling file by bare name, as a vendored institutional template does, stopped withFile ... not found. A newlatexmkrcat the repository root adds-synctex=1to every engine, so a command-line build no longer deletes the.synctex.gzthat editor-to-PDF jumps read. An existing thesis keeps its own.vscode/settings.json, and an update does not installlatexmkrc, so copy the twolatex-workshop.latex.external.build.*keys andlatexmkrcfrom upstream by hand. - 2026-09-27 — Manuscript files follow one owner-key scheme,
<key>_<slug>.<ext>, so a directory lists in the same order in git and the terminal as in VS Code, Overleaf, and Finder (§5 of the conventions, Manuscript file names): one_, between the key and a lowercase slug whose words are joined by-. Chapters aremanus/chaps/<nn>_<slug>.texwith a two-digit key (a thesis with nine or fewer chapters on one-digit keys may keep them, but every key in a directory has one width), appendices and other back mattermanus/backs/<letter>_<slug>.tex, and a figure, its editable source, and a table take the key of the one chapter or appendix that includes them (00for front matter, or0in a thesis that keeps one-digit chapter keys), with no ordinal of their own:manus/figs/<owner>_<slug>.pdf,manus/figs/srcs/<owner>_<slug>.*, andmanus/tabs/<owner>_<slug>.tex. A language twin ends in-zh, so the appendix starters are nowmanus/backs/a_supporting-material.texanda_supporting-material-zh.tex;manus/fronts/stays unprefixed. On a confirmed renumber, split, or merge,story-outl-plannermoves a chapter's figures, sources, and tables with it and rewrites their paths, andstory-figs-designerandstory-tabs-buildername each file after its outline row'sChaptercell.lint.shnow warns, without failing, on a name off the scheme, a directory whose byte and numeric orders differ, whose keys mix widths, or whose slugs differ only in a number's leading zeros, a key no chapter, appendix, or front matter holds, and an include whose asset carries another file's key. An update never touchesmanus/, so rename an existing thesis's files by hand, in one commit: rungit mv manus/backs/a_supporting_material.tex manus/backs/a_supporting-material.texandgit mv manus/backs/a_supporting_material_zh.tex manus/backs/a_supporting-material-zh.tex, then change\input{backs/a_supporting_material}inmanus/main.texand\input{backs/a_supporting_material_zh}inmanus/main-zh.texto the new names (or keep the old names and accept the lint warning); optionally widen one-digit chapter keys to two digits; re-key each figure, source, and table to the file that includes it; and rewrite the\inputand\includegraphicslines and every path cell innotes/andtasks/that names a renamed file.lint.shreads manuscript sources as TeX does. A\todowhose argument a comment or line break splits, one after\verb|50%|, one in a file with lone-CR line ends, and each of several on one line now count, and an\inputof a chapter split the same way wires it. A.texfile or directory undermanus/that lint cannot read, a.texfile saved as UTF-16 or UTF-32, an unreadable entry point, and an unreadabledegree/profile.texnow fail lint instead of passing as clean, and a byte that is not UTF-8 in a source, the profile,.env, or a milestone record no longer stops lint orrun.sh: the file is read byte by byte, with one warning. The status scan'stodo markers:count now follows lint's rules, and names any file it could not count. - 2026-09-24 — Fresh-session scenario runs found three instruction gaps, now closed.
AGENTS.mdnow spells out what conventions §8 already required of every run, with or without a skill: a change undermanus/ends withbash execs/run.shand, only when it succeeds,bash execs/scpts/lint.sh --no-build; and the handoff names the exact command for the earliest unmet gate, an author action when only you can clear it, the action that clears a blocked or failed step, or, only when no gate remains anywhere in the pipeline,Next action: none — the requested workflow is complete.word for word, never a paraphrase or a second suggestion; and a completion report names the built PDF, page count, lint verdict, ledger changes, and remaining gates.story-copy-editor styleon a sample you name records the sample's path and proposes the other fields' wording in its report, writing a field only once you confirm it. Fields always held only empty or author-confirmed text, but an earlierstylerun on a sample may have filled one with its own reading, so checknotes/style.mdif you ran one. A run that finds an earlier release's memory index or a.zh-CN.mdtwin names folding and deleting it as your action instead of offering to do it (conventions §1 and §10).AGENTS.mdalso names registering a corrected manual artifact as a new record, and atasks/audits.mdsection readsLast full run: noneuntil a thesis-wide audit dates it. Astory-autogoal run's final reply now opens with its check and resolved level, since text between tool calls may never reach you, andstory-flow-statusreports the supervision record only through its open promises. - 2026-09-24 — The frontmatter descriptions of
story-cite-auditorandstory-refs-curatorare valid YAML again: an unquoted:in each made a strict parser reject the block and drop the skill's routing text, andcheck_consistency.shnow fails on such a value. A prompt audit against current models also tightened the text in a few places, without changing a rule:story-copy-editor's description names itsstyletarget, and neitherstory-cite-auditornorstory-depo-packerany longer implies an announced edit is allowed. In the conventions, the evidence-verdict,tasks/key,active_milestonefallback, and lint-warning sentences now match the code and the skills that apply them. Four contradictions the audit found are settled: the author, not a skill, carries an earlier release's memory index intosummaryfields, folds its twins, and deletes the old files (§10, now matching §1 andAGENTS.md); an outline row isreadyonly when every claim its artifact states has currentStated inandEvidencecells innotes/claims.md, in the definition and the setter rule alike (§3); every provenance hook but Codex's, when it yields no usable id, now tells the model to copy an id the session's own context states outright and to writeunrecordedonly when none is stated, the order §7 already gives (Codex's still falls back tounrecorded, because its--checkexpects that value); and the commit guard's forced-push denials say to leave the push to the user. - 2026-09-24 — The milestone directory
milestones/is nowmiles/, matching the other abbreviated names such asmates/,manus/,notes/, andtasks/; every skill,lint.sh, the status scan, and the gates that guard received feedback read onlymiles/. An update moves nothing: rungit mv milestones milesin an existing thesis and commit it, and the updater reports a leftovermilestones/until you do (Updating STORY). An existing thesis keeps its own.editorconfig, so change its twomilestones/template sections tomiles/by hand. - 2026-09-24 — A thesis can carry abstracts in both languages:
\begin{storyabstract}[en|zh]and\storykeywords[en|zh]{...}name each abstract's language, and the newcjkclass option lets an English thesis typeset a Chinese abstract under XeLaTeX or LuaLaTeX (English and Simplified Chinese).degree/profile.texgains\submissionstatement, the title-page statement above the degree name, which ships as a placeholder.lint.shreads level wording from the degree field only and checks the language option only under STORY's class; it takes the page count from the build log whenpdfinfois missing and warns when it cannot check a page limit, warns on missing characters, an unsetdissertation_language, or a profile with no\submissionstatement, and fails on an invaliddissertation_language.import.sh --diffprints astale,new upstream, orremoved upstreamline per file and exits2only for the first two, and only astaleline makes a file stale.fmt.shkeeps a closing}or]on its sentence's line and refuses a rewrite that adds or drops a space beside one. The commit guard also declines a+refspecpush, deleting a remote branch or tag, andupdate-refon a tag.execs/update.shnow works with Git 2.25–2.36, whose sparse checkout does not start in cone mode;--adoptalso installsmanus/main-zh.texand, when it keeps a.gitignore, notes one that leaves.envunignored or ignores evidence undermates/, which the template's own.gitignorenever ignores. An update deletes nothing, so delete by hand a leftover Chinese instruction twin, such as.agents/commands/story.zh-CN.md, which this release drops, orskills/story/SKILL_zh.mdin either plugin tree (.codex/plugins/story/,.kimi-code/plugins/story/), or a folded workflow spec. An update or--adoptthat keeps a.latexindent.yamlwithout the closing-brace rules says so,import.shwarns when an ignore rule would leave an imported file untracked, and the status scan reports a PDF whose build log is missing as a stale build. The conventions settle whatweakenedmeans (a confirmed narrower scope not yet in the wording), reopen an audit line whose failure returns, return an outline row toin-progresswhen a write leaves it unfinished, name who retires a claim, and tighten deposit gates 1 and 7;story-chap-drafteradapts published material only under anin-scopeorclearedpublication row, and/story-autoasks each target only for the inputs it needs. The memory hooks read a quotedverifieddate as a date; the Qwen Code resolver reads past a malformed transcript line, Kimi Code's provenance line says to copy the configured model id verbatim, and Codex's--checkaccepts the id--resolvegives. An existing thesis keeps its own.gitignore,.cursorignore,.vscode/settings.json,.latexindent.yaml,.editorconfig,degree/profile.tex, andmanus/, which an update does not overwrite, so apply these changes by hand: add!/mates/**to.gitignoreafter the LaTeX build-file rules and before.DS_Store, with a.envline right after it, and!mates/**at the same place in.cursorignore; setlatex-workshop.latex.autoClean.runto"never", so an editor build stops deleting the log thatlint.sh --no-buildand the status scan read; copy the two closing-brace rules undermodifyLineBreaksfrom upstream's.latexindent.yaml, without which the newfmt.shrefuses any file where a sentence ends a group; setcharset,end_of_line, andinsert_final_newlinetounsetin.editorconfig's style-layer and template sections; add a\submissionstatementline before\degreeindegree/profile.tex; copymanus/stys/story.clsfrom upstream for per-language abstracts andcjk; and copymanus/main-zh.texfrom upstream if an earlier--adoptleft it out, sinceSTORY_MAIN=manus/main-zh.texneeds it. - 2026-09-23 — Who sets each ledger status is now one rule, §3 of the conventions (Who sets each status), and a deposit is ready only when
story-depo-packerreports every gate of §6 (Deposit gates) as passing, a clean Git tree and both audits run after the last change among them; it records the source commit in the RECORD and tags it only when you confirm.story-chap-drafteralso drafts one front- or back-matter file, andtrace CHAPTERadds missing source anchors without changing typeset text. Informal supervisor or coauthor feedback goes to a standingmilestones/supervision/record, andstory-exam-reviewerwriteswkdrs/reports/SIM_EXAM_<date>.mdwhen no milestone is named or active, never creating one.story-proj-adoptcopies the draft rather than moving it, after you commit a checkpoint. The template'sdegree/profile.texnow ships% thesis_type:empty rather thanmonograph, andstory-outl-plannerasks for it; every skill's argument hint ends with[involve=LEVEL]. - 2026-09-23 —
/story-auto <goal>($story-autoin Codex) pursues a goal: it runsstory-flow-status, starts the ten unmarked skills each handoff names, asks you at everyAGENTS.md§1 ask-first choice, and stops at a † skill or a gate only the author can clear; it never imports evidence, writesdegree/or received feedback, declares a deposit ready, commits, or pushes (Goal runs). Claude Code gainsstory_bash_gate.sh, which answers its shell prompt atINVOLVE=lowoutside the red lines and follows theinvolve=token you last typed; every gate keeps the prompt for a write intomates/,degree/, ormilestones/*/feedback/, and Pi gains the commit guard. The provenance read is quoted for zsh and pre-allowed in.claude/settings.json, and Codex adds a post-write--check. Each memory file now carries a one-linesummary, from which the hooks build the index (--listprints it), and the template ships only.story/memory/.gitkeep. The human-writing guide, the memory spec, and the model-id fallbacks fold into the workflow conventions as §5, §10, and the new §11 harness adapters, the one section that names a harness. Instructions are English only:SKILL_zh.md,AGENTS.zh-CN.md, and the other instruction twins are gone, a Chinese run still replies in Chinese, and a thesis deletes its leftover copies by hand, as Updating STORY lists.story-flow-statusruns ateffort: mediumin Claude Code, andlint.shfails on a failed build and reads the page limit from the active milestone. An older updater stops withUpstream ref is missing AGENTS.zh-CN.md: replaceexecs/update.shonce by hand, as Updating STORY describes. An existing thesis keeps its own.claude/settings.jsonand.codex/hooks.json: merge the bash-gate registration and the three allow rules (Hooks and permissions) and Codex's separate memorySessionStartgroup by hand (the updater reports a missing gate, a missing resolver rule, and the old grouping), and install the Codex or Kimi Code plugin again to get/story-auto.
See LICENSE.
