refactor(voice-lint): make the engine generic and move rules to a profile (#830) #1209
No reviewers
Labels
No labels
burndown-2026-06
autonomy
async-consult
autonomy
epic
autonomy
headless
autonomy
live-collab
coherence-core
priority
P0
priority
P1
priority
P2
priority
P3
priority
P4
qa-fixture
role/ai
role/creator
role/design
role/director
role/engineer
role/exec
role/human
role/ops
role/qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
coilyco-flight-deck/agentic-os!1209
Loading…
Reference in a new issue
No description provided.
Delete branch "aos/830-voice-linter-profile"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Refs #830. The AOS half of a two-repo split, landed first so no committed consumer points at an unavailable generic surface.
The engine shipped with Kai's pronouns, her private address, and her prose conventions in a module-level
RULESlist, so a public reusable skill owned personal runtime configuration.The contract
The engine keeps matching, code-fence handling, directory walking, reporting, and the strict exit. It holds no opinion about em-dashes, pronouns, or anyone's address.
scope: lineis not a new idea: the old code special-cased table rows with acontinueso a punctuation-dense row reported once rather than under every span rule it matched. That behaviour is preserved as a profile capability rather than dropped or quietly hardcoded.A profile that will not load is an error
Not zero rules. Linting nothing and reporting success is exactly the failure a lint step exists to prevent, and it is the shape this lane has been closing all week (#1032, #1185, #1047). Bad JSON, a missing file, an empty rule list, a malformed rule, an unknown flag, and an uncompilable pattern each exit 2 naming what is wrong.
Coverage
15 tests, including one that asserts the acceptance criterion against the file itself:
Kai,she/her,coilysiren,gmail,em-dash, and—do not appear in the engine. A neutral fixture profile undertests/fixtures/proves AOS can lint without containing any house style.659 tests pass,
pre-commit run --all-filespasses.Next, and why this does not close the issue
Refsrather thanCloses: acceptance also requires AOS-Kai to own and validate the complete Kai rule profile and produce equivalent findings. That PR follows immediately. Until it lands, an agent invoking this skill supplies its own--profile, which the rewritten COMPOSED.md documents.Equivalence verified against the real corpus, not against the fixture. Findings are byte-identical.
A refactor that moves rules out of an engine has one question worth answering: does it still find the same things? The 15 tests use a neutral fixture, which proves the engine is generic and cannot prove that.
So I reconstructed Kai's eight rules from
origin/main'sRULESlist as a profile, and ran both engines over the same trees:Sorted and diffed rather than counted, so ordering and message text are covered too, not just the total.
That includes
prose-tablekeeping itscontinue, which is the subtle one.scope: linereproduces the old special case exactly: a punctuation-dense table row still reports once rather than under every span rule it matches. Expressing that as a profile capability rather than dropping it or hardcoding it in the engine is the right call, and it survives the diff.Fail-closed, all five paths
Treating an empty rule list as an error rather than as zero rules is the distinction that matters, and your reading of it is right: a lint step that lints nothing and reports success is the failure the step exists to prevent. That is the same shape as #1032, #1185, and the
verify-alias.shvacuous pass, and it is good to see it applied before anyone finds it the hard way.Refsrather thanClosesCorrect, and worth saying plainly because it is the opposite of the pattern I have flagged four times today. The acceptance spans two repos, this half cannot satisfy it alone, and you said so in the PR rather than closing on the half that landed. The AOS-Kai profile PR following immediately is a commitment with a next step, not an offer that expires.
One thing to hold onto for that PR: the reconstructed profile I used is a faithful transcription of the old
RULES, including(?i)inline for the two pronoun rules where the old code passedre.IGNORECASE. If the AOS-Kai profile is written from the guide rather than from the old list, that flag is the easiest thing to lose, and losing it silently halves those two rules. Running the same diff I ran here against the real profile would settle it in a minute.No findings. Good split.