Repository navigation
Description
.ste-budget in this repo is 110, seeded from this count when the check was adopted so CI is green today. This issue is the list to work down.
Some of this prose also feeds tunaos.org: sync-org-docs.mjs copies this repo's README and the top level of its docs/ tree into tuna-os/docs as docs/<slug>/, where the aggregator deliberately skips synced trees — a fix made there is reverted by the next sync. Nested paths such as docs/reports/ or docs/adr/ are not copied at all, so a good share of the findings below never reach the site.
Either way the prose is authored here, so here is where it gets fixed — which is the whole reason the check was moved out of the aggregator and into the source repos.
By rule
| Rule | What it means | Count |
|---|---|---|
| STE 4.1 | -ing forms |
45 |
| STE 1.4 | noun clusters (max 3 words) | 23 |
| STE 3.2 | sentence length, description (max 25 words) | 18 |
| STE 3.4 | active voice | 13 |
| STE 1.5 | approved words | 6 |
| STE 3.1 | sentence length, instructions (max 20 words) | 5 |
By file
| File | Count |
|---|---|
docs/USER_GUIDE.md |
31 |
docs/OBSERVABILITY.md |
27 |
CONTRIBUTING.md |
11 |
README.md |
10 |
docs/recipes/auto-captions.md |
8 |
docs/adr/0004-vello-uri-bridge.md |
7 |
docs/adr/0001-rust-ges-gtk-stack.md |
6 |
docs/observability.md |
6 |
docs/adr/0002-json-document-ts-scripting.md |
4 |
Findings
The first 50 of 110, in file order. Run the linter locally (below) for the rest — the full list is long enough that pasting it here would bury the summary.
docs/USER_GUIDE.md
docs/USER_GUIDE.md:3— STE 3.4: passive voice ("are regenerated"); say who or what does the actionScreenshots on this page are regenerated automatically on every release by (the app's mode), so
docs/USER_GUIDE.md:9— STE 3.2: sentence is 34 words; the limit is 25 for descriptive textLaunch Dualcut from your app menu and you get an unsaved New Project, scaffolded with a title sc
docs/USER_GUIDE.md:12— STE 1.4: noun cluster of 4 words ("arrow lists recent ones"); use at most 3, and add prepositionsUse Open for an existing project (the arrow lists recent ones), or pass a path on the command li
docs/USER_GUIDE.md:19— STE 3.2: sentence is 46 words; the limit is 25 for descriptive textOne window, four regions: the Clips / Library / Templates / Code / Script tabs on the left, the
docs/USER_GUIDE.md:19— STE 3.4: passive voice ("is selected"); say who or what does the actionOne window, four regions: the Clips / Library / Templates / Code / Script tabs on the left, the
docs/USER_GUIDE.md:32— STE 3.2: sentence is 30 words; the limit is 25 for descriptive textImport (header or the Library tab's empty state) adds media files to the project's library — or
docs/USER_GUIDE.md:32— STE 1.5: "just" adds nothing; delete itImport (header or the Library tab's empty state) adds media files to the project's library — or
docs/USER_GUIDE.md:38— STE 3.4: passive voice ("are automatically transcoded"); say who or what does the actionImported videos are automatically transcoded in the background into lightweight proxy media (960
docs/USER_GUIDE.md:40— STE 3.2: sentence is 26 words; the limit is 25 for descriptive textThe preview and timeline scrub through these proxies for smooth playback even with 4K footage, while
docs/USER_GUIDE.md:51— STE 4.1: "-ing" form ("selecting"); use a simple verb or a nounShip your own by selecting clips and using Save as template.
docs/USER_GUIDE.md:58— STE 3.2: sentence is 27 words; the limit is 25 for descriptive textEdit it directly and press Apply JSON; the change is validated, undoable, and hot-reloads the prev
docs/USER_GUIDE.md:58— STE 3.4: passive voice ("is validated"); say who or what does the actionEdit it directly and press Apply JSON; the change is validated, undoable, and hot-reloads the prev
docs/USER_GUIDE.md:66— STE 3.2: sentence is 28 words; the limit is 25 for descriptive textWhere Code shows the document, Script transforms it: write a TypeScript function , press *Run scr
docs/USER_GUIDE.md:69— STE 4.1: "-ing" form ("renaming"); use a simple verb or a nounUseful for bulk operations — renaming scenes, retiming clips, generating layers from data.
docs/USER_GUIDE.md:69— STE 4.1: "-ing" form ("retiming"); use a simple verb or a nounUseful for bulk operations — renaming scenes, retiming clips, generating layers from data.
docs/USER_GUIDE.md:69— STE 4.1: "-ing" form ("generating"); use a simple verb or a nounUseful for bulk operations — renaming scenes, retiming clips, generating layers from data.
docs/USER_GUIDE.md:74— STE 3.2: sentence is 37 words; the limit is 25 for descriptive textSelect a clip in the timeline, preview, or Inspect list to edit its timing, transform, and text; add
docs/USER_GUIDE.md:83— STE 3.2: sentence is 29 words; the limit is 25 for descriptive textClick a scene segment in the timeline ruler to edit its duration and the transition from the previou
docs/USER_GUIDE.md:94— STE 3.2: sentence is 36 words; the limit is 25 for descriptive textPairs with two starter templates in the Templates tab: vertical-center-crop (scales and centers
docs/USER_GUIDE.md:98— STE 1.5: "just" adds nothing; delete itBoth are plain composition — transform math on ordinary video clips — so they work with any project,
docs/USER_GUIDE.md:105— STE 3.2: sentence is 34 words; the limit is 25 for descriptive textSpace plays/pauses, Left/Right steps one frame, Home/End jumps to the start/end, S splits the select
docs/USER_GUIDE.md:107— STE 4.1: "-ing" form ("showing"); use a simple verb or a nounThe hamburger menu's Keyboard Shortcuts opens a reference showing whatever is currently bound — se
docs/USER_GUIDE.md:107— STE 1.5: "currently" is not approved; use "now"The hamburger menu's Keyboard Shortcuts opens a reference showing whatever is currently bound — se
docs/USER_GUIDE.md:111— STE 3.2: sentence is 42 words; the limit is 25 for descriptive textEvery shortcut is rebindable in Preferences → Keyboard Shortcuts: click any shortcut and press the
docs/USER_GUIDE.md:114— STE 3.2: sentence is 37 words; the limit is 25 for descriptive textPresets only remap the actions dualcut actually has — where an app's shortcut assumes a feature dual
docs/USER_GUIDE.md:114— STE 1.5: "actually" adds nothing; delete itPresets only remap the actions dualcut actually has — where an app's shortcut assumes a feature dual
docs/USER_GUIDE.md:121— STE 3.2: sentence is 113 words; the limit is 25 for descriptive textThe hamburger menu holds New Project, New Vertical Project (9:16), Save Project As…, *Generate
docs/USER_GUIDE.md:121— STE 3.4: passive voice ("is greyed"); say who or what does the actionThe hamburger menu holds New Project, New Vertical Project (9:16), Save Project As…, *Generate
docs/USER_GUIDE.md:121— STE 1.4: noun cluster of 4 words ("small English speech model"); use at most 3, and add prepositionsThe hamburger menu holds New Project, New Vertical Project (9:16), Save Project As…, *Generate
docs/USER_GUIDE.md:121— STE 1.4: noun cluster of 4 words ("different ggml model path"); use at most 3, and add prepositionsThe hamburger menu holds New Project, New Vertical Project (9:16), Save Project As…, *Generate
docs/USER_GUIDE.md:138— STE 3.2: sentence is 32 words; the limit is 25 for descriptive textEverything above has a programmatic twin: the project file hot-reloads when edited on disk, an HTTP
docs/OBSERVABILITY.md
docs/OBSERVABILITY.md:5— STE 1.4: noun cluster of 6 words ("native Rust-based non-linear video editor engine"); use at most 3, and add prepositionsis a native Rust-based non-linear video editor engine ( ) built on top of GStreamer ( , , , ), GT
docs/OBSERVABILITY.md:9— STE 1.4: noun cluster of 5 words ("HTTP Local Host File API"); use at most 3, and add prepositionsHTTP Local Host File API ( ):
docs/OBSERVABILITY.md:10— STE 1.4: noun cluster of 4 words ("local HTTP API server"); use at most 3, and add prepositionsexposes a lightweight, local HTTP API server ( ) bound exclusively to .
docs/OBSERVABILITY.md:11— STE 4.1: "-ing" form ("scripting"); use a simple verb or a nounUsed for agent scripting, project inspect/edit ops ( , , ), and engine status checks ( ).
docs/OBSERVABILITY.md:12— STE 3.4: passive voice ("are performed"); say who or what does the actionNo external data transmission or remote network calls are performed by the API server.
docs/OBSERVABILITY.md:14— STE 4.1: "-ing" form ("Tracing"); use a simple verb or a nounLogging & Diagnostic Tracing:
docs/OBSERVABILITY.md:16— STE 4.1: "-ing" form ("formatting"); use a simple verb or a nounRust standard library formatting and context chains propagate operational errors across pipeline c
docs/OBSERVABILITY.md:16— STE 4.1: "-ing" form ("loading"); use a simple verb or a nounRust standard library formatting and context chains propagate operational errors across pipeline c
docs/OBSERVABILITY.md:16— STE 1.4: noun cluster of 5 words ("context chains propagate operational errors"); use at most 3, and add prepositionsRust standard library formatting and context chains propagate operational errors across pipeline c
docs/OBSERVABILITY.md:19— STE 3.4: passive voice ("is currently configured"); say who or what does the actionNo telemetry backend is currently configured or authorized for external data export.
docs/OBSERVABILITY.md:19— STE 1.5: "currently" is not approved; use "now"No telemetry backend is currently configured or authorized for external data export.
docs/OBSERVABILITY.md:20— STE 3.1: sentence is 23 words; the limit is 20 for instructionsStandard telemetry policy prohibits introducing external metric exporters, OpenTelemetry SDK collect
docs/OBSERVABILITY.md:20— STE 3.4: passive voice ("been explicitly configured"); say who or what does the actionStandard telemetry policy prohibits introducing external metric exporters, OpenTelemetry SDK collect
docs/OBSERVABILITY.md:20— STE 4.1: "-ing" form ("introducing"); use a simple verb or a nounStandard telemetry policy prohibits introducing external metric exporters, OpenTelemetry SDK collect
docs/OBSERVABILITY.md:20— STE 1.4: noun cluster of 4 words ("Standard telemetry policy prohibits"); use at most 3, and add prepositionsStandard telemetry policy prohibits introducing external metric exporters, OpenTelemetry SDK collect
docs/OBSERVABILITY.md:21— STE 4.1: "-ing" form ("scoping"); use a simple verb or a nounAny future telemetry integration must maintain local-only scoping, strict attribute cardinality cont
docs/OBSERVABILITY.md:21— STE 1.4: noun cluster of 4 words ("strict attribute cardinality controls"); use at most 3, and add prepositionsAny future telemetry integration must maintain local-only scoping, strict attribute cardinality cont
docs/OBSERVABILITY.md:25— STE 3.4: passive voice ("be designated"); say who or what does the actionShould an operational backend be designated in the future, the following bounded instrumentation arc
docs/OBSERVABILITY.md:25— STE 3.4: passive voice ("is recommended"); say who or what does the actionShould an operational backend be designated in the future, the following bounded instrumentation arc
Running it locally
mkdir -p /tmp/ste && cd /tmp/ste
for f in ste-lint.mjs ste-rules.mjs; do
curl -fsSLO "https://raw.githubusercontent.com/tuna-os/.github/main/.github/actions/ste-lint/$f"
done
cd - && node /tmp/ste/ste-lint.mjs # full detail
node /tmp/ste/ste-lint.mjs --summary # counts only
node /tmp/ste/ste-lint.mjs README.md # one fileHow to close this
The budget is a ratchet: lower .ste-budget whenever a batch of prose lands, never raise it to make a PR pass. Clear findings in whatever order suits — there is no need to do it in one pass, and partial progress is worth landing.
Not every finding must be rewritten. A file can opt out in its own text with a stated reason — the reason is what stops the opt-out list from becoming where prose goes to be forgotten. Published records (dated blog posts), documents quoted verbatim (the Contributor Covenant), and bibliographies reproducing others' titles are all legitimate opt-outs. Judgement calls about whether a rule improves a given sentence are for whoever knows the prose, not the linter.
The linter and its rules live in tuna-os/.github.
Activity
castrojo commentedon Oct 23, 2026
Resolved by open PR #245 — docs: clear all STE100 prose findings (#163) (castrojo:fix/ste-prose-findings, base
main).Verified against the canonical gate (tuna-os/.github ste-lint action):
node ste-lint.mjs --max 0over the gate targets (docs/, README.md, CONTRIBUTING.md) returns 0 findings, exit 0. All 110 findings cleared by prose rewrites — noste-disableopt-outs, so nothing was suppressed..ste-budgetratcheted 110 -> 0 (never raised to pass).Note: the linter also flags ~118 findings in files outside this issue\u0027s scope (root ROADMAP.md, AGENTS.md, CONTEXT.md, CLAUDE.md, skills/, runbooks/) — those are not in the STE gate targets and are not part of this issue.
PR is ready for maintainer review; it will auto-close this issue on merge.
— hive: backend=omp model=lab-worker/ornith
🐝 Hive Agent:
contributor| SHA:unknowncastrojo commentedon Oct 23, 2026
Working PR for this issue: #246 — docs: clear STE100 prose findings (#163) (castrojo:fix/ste100-prose-findings, base
main).Verified with the canonical gate (tuna-os/.github ste-lint action):
node ste-lint.mjs --max 0over the gate targets (docs/, README.md, CONTRIBUTING.md) exits 0 with 0 findings. Positive control onupstream/mainreports 98 findings across 8 files, so the pass is real, not vacuous. All fixes are prose rewrites — noste-disableopt-outs, nothing suppressed..ste-budgetratcheted 110 -> 0.(Prior session opened #245 on the same prose; #246 is the working PR for this task.)
Ready for maintainer review; it will auto-close this issue on merge.
— hive: backend=omp model=lab-worker/ornith
🐝 Hive Agent:
contributor| SHA:unknown