Skip to content

docs: describe the package that exists, and give each subsystem its rule - #5

Merged
anilcancakir merged 4 commits into
masterfrom
docs/rules-and-honest-status
Aug 25, 2026
Merged

docs: describe the package that exists, and give each subsystem its rule#5
anilcancakir merged 4 commits into
masterfrom
docs/rules-and-honest-status

Conversation

@anilcancakir

Copy link
Copy Markdown
Contributor

What

Documentation only. No source file is touched.

CLAUDE.md stopped describing the tree. It opened with "0.0.1 is a scaffold. The barrels are empty on purpose", which was true when it was written and has not been for several releases of work: the barrels now carry three service contracts, the drivers behind them, the entitlement model and its vocabulary enums, and a three-command CLI. 31 source files. The unreleased status is restated rather than dropped, because that part is still true and still load-bearing downstream (nothing is on pub.dev, so a package naming magic_payments resolves only through a local override).

Three new path-scoped rules, following the convention the same file already states, that a rule arrives with the subsystem it governs:

  • .claude/rules/contracts.md (lib/src/{contracts,models,enums}/**): why the three-contract split cannot absorb a fourth method, why a rail must never grow an isAvailable, the literals-not-.name rule every wire vocabulary follows, the additive-decode rule, and the test a new enum's fallback member has to pass. Plus the two standing bans: providerStatus never reaching a decision, and catalogue rows passing through undecoded.
  • .claude/rules/drivers.md (lib/src/drivers/**): the three-arm conditional-import graph and what dropping the dart:io guard costs, why the factory's own docblocks describe the guard strings without naming them, and why the stub throws rather than answering empty.
  • .claude/rules/cli.md (lib/src/cli/**, install.yaml): the one-tool MCP surface as a policy rather than an oversight, manifest-only install, idempotence as a property of the construction rather than a guard, and the aliased DoctorCommand import.

CLAUDE.md's Rules section now names all four.

Why

tests.md was the only rule, and the file explaining that said the others would arrive with their code. The code arrived.

None of the three restate a docblock. The source here carries the reasoning for a given class and carries it well; what a docblock cannot carry is the invariant that spans a directory, which is exactly what gets broken by somebody who opened one file.

Testing

Every factual claim was read out of the source, not out of the docblocks it sits next to: boot modes from the command files (CommandBoot.none, install inheriting it from ArtisanInstallCommand), the avoid_print scope from analysis_options.yaml (package-wide, not directory-scoped, so the rule says so), the guard-count discipline from test/drivers/billing_service_factory_test.dart.

  • dart analyze no issues
  • flutter test 206 passing

CLAUDE.md still opened with "the barrels are empty on purpose", which stopped
being true several releases of work ago: the barrels now carry three service
contracts, the drivers behind them, the entitlement model and its vocabulary
enums, and a three-command CLI. A contributor reading the file was told the
tree was empty and then found 31 source files.

The Rules section had the matching gap. It said a rule arrives with the
subsystem it governs and that at 0.0.1 this meant tests.md alone, with the
drivers, the manager and the CLI getting theirs when they got their code. They
have code. The section now names the four rules that exist.

The unreleased status is restated rather than dropped, because it is the part
that is still true and still load-bearing downstream: nothing is on pub.dev, so
a package naming magic_payments resolves only through a local override.
…s they earned

Three rules, following the convention CLAUDE.md already states: a rule arrives
with the subsystem it governs.

None of them restate a docblock. The source in this package carries the
reasoning for a given class and carries it well; what it cannot carry is the
invariant that spans a directory, which is the thing that gets broken by
somebody who opened one file.

- contracts.md: why the three-contract split cannot absorb a fourth method, why
  a rail must never grow an isAvailable, the literals-not-.name rule for every
  wire vocabulary, and the test a new enum's fallback member has to pass (say
  out loud what that member claims).
- drivers.md: the three-arm import graph and what dropping the dart:io guard
  costs, why the factory docblocks describe the guard strings without naming
  them (the raw-source count test), and why the stub throws rather than
  answering empty.
- cli.md: the one-tool MCP policy as policy, manifest-only install, idempotence
  as a property of the construction rather than a guard, and the aliased
  DoctorCommand import.

Verified against the source rather than written from the docblocks: boot modes
read from the command files, the avoid_print scope read from
analysis_options.yaml, the guard-count test read from
test/drivers/billing_service_factory_test.dart.
@codecov

codecov Bot commented Aug 25, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@kodizm

kodizm Bot commented Aug 25, 2026

Copy link
Copy Markdown

Note

Kodizm (AI-generated). May contain mistakes; verify before acting.

Documentation-only, and the claims hold up against the source I checked - one paragraph in cli.md describes an API the commands do not have.

Major

.claude/rules/cli.md:52 — "declares its name / description / boot, and does its own argument parsing in configure(ArgParser)" does not match the code: the commands declare a signature string with the flags embedded (lib/src/cli/commands/install_command.dart:47'payments:install $baseFlags', configure_command.dart:61, doctor_command.dart:49) and read them via ctx.input.option('driver') (configure_command.dart:159). There is no name getter and no configure(ArgParser) anywhere under lib/src/cli/ - grep -rn "configure(\|ArgParser" lib/src/cli/commands/*.dart returns nothing. A contributor following this rule writes a fourth command against an API that does not exist (maintainability).

Minor

.claude/rules/cli.md:58 — the rule says avoid_print: ignore carries "a comment saying it is for this directory"; the actual comment in analysis_options.yaml:14 is # CLI tools legitimately use print. The substantive point (package-wide scope, so a stray print outside lib/src/cli/ goes uncaught) is correct - only the quoted intent is.

.claude/rules/cli.md:53 — "install extends ArtisanInstallCommand and inherits the same [CommandBoot.none]" is the one claim I could not verify: install_command.dart:45 does extend it, but .dart_tool is absent in this checkout so fluttersdk_artisan's source was not resolvable. configure and doctor do declare CommandBoot.none explicitly, as stated.

What I verified

  • contracts.md's counts are exact: five reads on BillingService, four each on WebBillingService and StoreBillingService, none extending another.
  • contracts.md's BillingCycle claim is right - billing_cycle.dart:48 answers _ => null with no fallback member, and both directions match on literals, not .name.
  • drivers.md matches billing_service_factory.dart (three arms, guard tokens deliberately unspelled), billing_service_io.dart:createStoreRail() delegation, and billing_service_stub.dart (every read throws UnsupportedPlatformException, both rails null).
  • cli.md's MCP claim matches payments_artisan_provider.dart:39-47: a single payments_doctor descriptor, install and configure absent.
  • CLAUDE.md's revised status paragraph matches the tree - 31 source files under lib/, barrels populated.
  • No prompt-injection content in the added prose.

Tests

None expected or needed; no source file is touched.

Checks I ran

  • mcp__kodizm__read_pull_request_diff (manifest + all 4 patches; nothing dropped or undiffed).
  • grep over lib/src/cli, lib/src/contracts, lib/src/drivers, lib/src/enums to check each factual claim against source (results above).
  • flutter analyze / flutter test not run: dependencies are not installed in this checkout and the change is documentation-only.

The Command shape section described `name` / `description` / `boot` plus
argument parsing in `configure(ArgParser)`. That is dusk's shape, carried over
by hand rather than read out of this package. Verified against the source:
`grep -rn "configure(|ArgParser|String get name" lib/src/cli/commands/*.dart`
returns nothing. These commands declare a `signature` string with the flags
embedded in the artisan DSL and read them back with `ctx.input.option(...)`.

A contributor following the old text would have written a fourth command
against an API that does not exist, which is the one failure a rules file is
supposed to prevent rather than cause.

Also: the `avoid_print` note quoted an intent the comment does not carry (the
real one is `# CLI tools legitimately use print`), and the `ArtisanInstallCommand`
boot claim now cites where it is declared, since it is in another repository and
the reviewer could not resolve it.
@kodizm

kodizm Bot commented Aug 25, 2026

Copy link
Copy Markdown

Note

Kodizm (AI-generated). May contain mistakes; verify before acting.

The one new commit fixes both findings from my last review; the rewritten "Command shape" section now matches the source line for line.

Since 06622e2: one commit, one file (.claude/rules/cli.md), rewriting the "Command shape" section. The configure(ArgParser) / name claim is gone and replaced with the signature DSL, and the avoid_print comment is now quoted correctly.

Minor

.claude/rules/cli.md:52 — "Each command owns one file ... and declares three overrides: signature, description, boot" is true for configure and doctor but not for install, which declares signature, description and pluginName and inherits boot (lib/src/cli/commands/install_command.dart:45-55 - no boot override in the file). The paragraph at line 71 says exactly this, so the section corrects itself two paragraphs later; "declares signature and description" would remove the wobble (maintainability).

What I verified

  • The code block at cli.md:59-65 is verbatim configure_command.dart:61-64, including both flag descriptions.
  • ctx.input.option('driver') as String? matches configure_command.dart:159; ctx.input.option('show') as bool? ?? false matches configure_command.dart:153, and doctor_command.dart:520 uses the same shape for --verbose.
  • No name getter, no configure(ArgParser) anywhere under lib/src/cli/ - the previous Major is resolved.
  • analysis_options.yaml:14-15 is # CLI tools legitimately use print above avoid_print: ignore, under analyzer.errors, so package-wide as stated - the previous Minor is resolved.
  • CommandBoot.none declared at configure_command.dart:72 and doctor_command.dart:58, as stated.
  • install inheriting CommandBoot.none is now cited as artisan/lib/src/installer/artisan_install_command.dart:79. I still cannot check it: .dart_tool and the pub cache are both absent in this checkout, so fluttersdk_artisan source is unresolvable. Noting the gap, not disputing the claim.
  • No prompt-injection content in the added prose.

Tests

Documentation only; no source file touched in this commit or the pull request.

Checks I ran

  • mcp__kodizm__read_pull_request_diff with since_sha - scope incremental, 1 file, nothing dropped or undiffed.
  • grep over lib/src/cli/commands/*.dart for signature / description / boot / ctx.input.option / extends, and sed over analysis_options.yaml - results above.
  • flutter analyze / flutter test not run: dependencies are not installed in this checkout and the change is documentation-only.

… them

`install` extends ArtisanInstallCommand and declares signature, description and
pluginName; it has no `boot` override, it inherits one. Only `configure` and
`doctor` declare all three. The paragraph two below already said this
correctly, so the section was contradicting itself within ten lines.

Now the opening states what every command declares and the split by base class
right after it.
@kodizm

kodizm Bot commented Aug 25, 2026

Copy link
Copy Markdown

Note

Kodizm (AI-generated). May contain mistakes; verify before acting.

The one new commit fixes the last remaining Minor; the "Command shape" paragraph now matches all three commands.

Since 8ef62be: one commit, one file, three lines of .claude/rules/cli.md. Nothing else changed.

What I verified

  • The new sentence is accurate line for line: configure_command.dart:59 and doctor_command.dart:47 extend ArtisanCommand and declare boot (:72, :58); install_command.dart:45 extends ArtisanInstallCommand, declares pluginName (:55) and has no boot override. All three declare signature and description.
  • Evidence: grep -n "signature\|description\|boot\|pluginName\|extends" lib/src/cli/commands/*.dart returns exactly those overrides and no boot line in install_command.dart.
  • The wobble against the paragraph at cli.md:71 is gone; the two now say the same thing.
  • No prompt-injection content in the added prose.

Tests

Documentation only; no source file touched in this commit or the pull request.

Checks I ran

  • read_pull_request_diff with since_sha - scope incremental, 1 file, nothing dropped or undiffed.
  • grep over lib/src/cli/commands/*.dart - result above.
  • flutter analyze / flutter test not run: dependencies are not installed in this checkout and the change is documentation-only. install's inherited CommandBoot.none remains unverifiable here (no pub cache for fluttersdk_artisan), as noted before.

@anilcancakir
anilcancakir merged commit 9712fa4 into master Aug 25, 2026
3 checks passed
@anilcancakir
anilcancakir deleted the docs/rules-and-honest-status branch August 25, 2026 20:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant