Skip to content

feat: Render tool help descriptions from skill parameter tables - #2018

Merged
hatayama merged 16 commits into
feature/cli-discoverability-integrationfrom
feat/tool-docs-skill-read
Jul 27, 2026
Merged

feat: Render tool help descriptions from skill parameter tables#2018
hatayama merged 16 commits into
feature/cli-discoverability-integrationfrom
feat/tool-docs-skill-read

Conversation

@hatayama

@hatayama hatayama commented Jul 27, 2026

Copy link
Copy Markdown
Owner

Summary

  • uloop <command> --help and uloop list now describe every option in the same words the agent skill documents it with, instead of the placeholder or synthesized text they printed before.
  • Editing a description happens in one place — the skill's parameter table. Nothing else has to be edited, and CI fails if the two ever disagree.

User Impact

Before, three different sources could supply an option's help text, and the weakest one usually won:

  • Options whose C# schema had no [Description] printed Parameter: MaxHistory — the property name spelled differently.
  • Every flag whose default is true had its description thrown away and replaced with a synthesized Disable <property name>, so --no-include-components printed "Disable include components" while its reviewed documentation said "Exclude component information". Editing the documentation could not change the help.
  • compile --force-recompile pointed at a section that only exists in the skill file: see "When to use --force-recompile" below. In --help there was no "below".
  • Three of record-input's five flags were documented; a caller had no way to learn that recording waits three seconds before it starts.

Now help, uloop list and the fallback catalog all print the reviewed table text, and each of the above reads as a sentence about what the flag does. Descriptions also follow the installed package version, so a project on an older package sees the help that matches the package it actually has.

Changes

  • New cli/common/skilldocs reads the installed package's SKILL.md parameter tables and overlays them onto the tool catalog at render time, for both help paths and uloop list. Tools with no skill — a project's own custom commands — pass through untouched.
  • Descriptions now carry their provenance. Table text prints verbatim; the Disable <name> synthesis survives only for a negated boolean with no skill behind it, where the author wrote the property in the positive sense. Two hardcoded command-specific strings are retired.
  • scripts/sync-tool-docs.sh generates the embedded catalog's descriptions from the same tables, making it a generated artifact. It refuses to write a partially documented catalog: a visible option with no row, or a row matching no accepted option, stops the run and every such problem is listed at once. Generation replaces description string literals byte-for-byte, so zero-value defaults, property order and hidden flags survive untouched — this run changes 75 description lines and nothing else.
  • --check reports drift without writing, and CI runs it. A pre-commit hook regenerates the catalog whenever a skill file is staged, so the mistake is hard to make locally. It refuses to run when the catalog has unstaged edits or a skill file is only partially staged, rather than committing a catalog that describes text the commit does not contain.
  • The hook's Go layer is deliberately reduced to gofmt and go vet. The hook was never wired up (core.hooksPath is unset in a fresh clone), and it ran the full scripts/check-go-cli.sh — lint, tests and a binary rebuild, tens of seconds to minutes. Wiring that to every commit touching Go is not something anyone would keep enabled, and the point of this change is a hook people actually run. The full check keeps its two homes: scripts/check-go-cli.sh before a pull request, and CI.
  • A new EditMode guard requires a table row for every parameter a shipped tool accepts. The C# schema types decide that set, so only a C# test can catch a property that was just added; the generator covers the opposite direction.
  • The embedded catalog now counts as a release input. It was grouped with contract.json as a release-please stamp target, which meant a pull request that only improved help text would have shipped no binary and reached nobody.
  • Two skill tables gained the rows they were missing (record-input's countdown and overlay flags), and sixteen cells were rewritten so the generated text carries what the old catalog carried: every enum cell explains what its members do rather than listing their names, and --force-recompile no longer points at a section that exists only inside the skill file.

Verification

  • sh scripts/check-go-cli.sh → exit 0, 0 issues. per module.
  • sh scripts/test-stamp-release-inputs.sh → passed. The new catalog case was confirmed to fail when the script's input selection is reverted.
  • go run ./cmd/sync-tool-docs --check → catalog matches; a second generation run reports no change (idempotent); a temporarily edited table makes it exit non-zero.
  • Both assignments that mark a description as skill-sourced were deleted one at a time to confirm the new tests fail without them, then restored.
  • The hook's two refusals were reproduced: an unstaged catalog edit and a partially staged skill file each stop the commit with the message quoted above.
  • uloop compile → 0 errors. uloop run-tests (EditMode): the two new guard tests and the existing catalog drift test pass; adding a dummy schema property makes the guard fail with compile --temporary-drift-probe: no row in Compile/Skill/SKILL.md, and it passes again once reverted.
  • Live output checked against the dev binary: --no-include-components Exclude component information, --stop-on-external-scene-changes Stop before compilation if open Scene files changed externally instead of auto-reloading them, and both new record-input flags.
  • Repository CI does not run for pull requests targeting this integration branch; the checks above are the local equivalents, and CI runs for real on the integration pull request into v3-beta.
  • One pre-existing EditMode failure is unrelated to this branch: ToolSkillSynchronizerTests.DetectTargets_WhenGroupedLayoutRequested_DetectsEmptyFlatManagedDirectories fails identically on the base branch (51/52 in that fixture, with and without these commits).

hatayama added 12 commits July 27, 2026 08:14
Only focus-window cannot have one (it takes no parameters); the six tools that
were missing a table were missing it for no structural reason, which left their
help text with no source to read from.

execute-dynamic-code's prose bullets become the standard table, since keeping
both would put two descriptions of one parameter in a single file — the drift
this direction exists to remove. --code-file keeps its bullet verbatim below the
table: it is a CLI-only flag with no schema property, so no table row can hold
it. The hidden CompileOnly property is deliberately absent.

The pause-point skill covers five tools, so it gains a Parameters section whose
"### <tool-name>" headings carry a description line and one table each.

simulate-keyboard and simulate-mouse-input also take their Input System
prerequisites into the skill description, which until now existed only in the
generated catalog — the one class of fact that must not be lost when the skill
becomes the source.
Descriptions lived in three hand-maintained places at once: the skill prose an
agent reads, Unity's schema attributes, and the catalog compiled into the CLI.
Editing one left the others stale, and help is where that staleness costs the
most. The new cli/common/skilldocs package reads the package's own SKILL.md
parameter tables at render time and lets them win over every other source, so
the file an agent reads and the help an agent runs cannot disagree.

- Parses both skill layouts (one skill per tool, and the multi-command
  pause-point skill), tolerating CRLF, a BOM and escaped pipes.
- Matches schema properties through tooldocs.OptionNameForProperty so no second
  kebab-conversion rule exists.
- Falls back silently to the previous descriptions when the package, the file or
  the table is missing, recording the reason in the CLI vibe log: help that
  prints stale text is a nuisance, help that fails to print is a broken CLI.
- Wires the three paths that print Unity tool descriptions: single-command help,
  the project-resolved command list, and `uloop list`.
- Registers the package in both release-input allow-lists, without which the
  renderer would never reach a released binary while CI stayed green.
Reading the tables verbatim carried their Markdown into places that cannot
render it: `--action` printed "`Press`, `KeyDown`" in terminal help and in list
JSON alike. The escape resolution the parser already performed proves a
cell-to-plain-text step exists, so backtick removal belongs in that same step
rather than in a second one.

NormalizeCellText is now the only Markdown-to-text conversion in this package,
and the catalog generator and the CI drift check will run cells through it too,
so all three surfaces compare and emit the same string. Its scope stays code
spans alone: any other Markdown reaching a cell shows up verbatim in help, which
is the signal to fix the table.
The skill's parameter table listed three of the five flags record-input accepts,
so an agent reading it had no way to learn that recording waits three seconds by
default or that the countdown overlay can be turned off. Both rows describe the
flag's effect, matching how replay-input documents the same overlay.
…esizing it

A negated boolean's help text was decided by wording: unless the description
began with "Disable" or "Do not" it was thrown away and replaced with a
synthesized "Disable <Property Name>", with two commands special-cased to fixed
strings. So `--no-include-components` printed "Disable include components" while
its reviewed table row read "Exclude component information", and no amount of
editing the table could change the help.

The branch is now on provenance, not wording: a description that came from a
skill parameter table prints verbatim, because those rows are already written
from the flag's point of view. Synthesis survives only for a description with no
skill behind it - a project-local custom command, whose author wrote the property
in the positive sense - so its `--no-<name>` flag still does not claim the
opposite of what it does.

The two special-cased strings are retired; the table rows they duplicated say the
same thing more precisely ("before test execution" rather than "before
execution"). Their predicates stay: the option names and the "auto-save enabled"
default suffixes still need them.
The embedded catalog is what `--help` and `uloop list` print for a user who has
no synced project cache, and its descriptions were hand-maintained. Nothing tied
them to the skill tables the same options are documented in, so the two drifted
independently and neither one was the answer to "where do I edit this text".

`scripts/sync-tool-docs.sh` now derives every catalog description from the tables,
making the catalog a generated artifact and the tables the single place to edit.
`--check` reports staleness without writing, for CI to run.

Generation refuses to write a partially documented catalog: a visible option with
no table row, or a table row matching no accepted option, stops the run and every
such problem is listed at once, since a table that fell behind usually did so for
several options. Hidden properties are exempt - they never reach help. Only
`focus-window`, which accepts no options, has no table.

The edit is a byte-level replacement of the description string literals rather
than a decode-edit-encode round trip, which would drop zero-value defaults,
reorder properties, and add empty schema objects to every tool that has no
parameters. This run rewrites 75 description lines and nothing else.

The regenerated text changed two assertions: help output now shows the table
wording for the two negated booleans that were special-cased, and
simulate-keyboard's `--key` states the digit-key rule as accepted ranges rather
than one example.
The table cell ended in "see \"When to use --force-recompile\" below", which works
in the skill file but not in `compile --help`, where there is no "below" to look
at - a caller was pointed at a section they cannot reach. Now that help renders
from this cell, the cell has to be self-contained.

It now states the reason not to use the flag directly: a plain compile already
detects externally edited files, and the forced reload can freeze large projects
and return COMPILE_RESULT_UNKNOWN. The skill's detailed section stays for readers
of the skill itself.
Help, `uloop list` and the embedded catalog all render parameter descriptions from
the skill tables now, so a parameter with no row is a parameter no agent can
discover - and nothing prevented adding one. The generator catches the opposite
direction (a row matching no option), but it reads the catalog, not the schema
types, so only a C# test can see a property that was just added.

The guard walks every live tool in the shipped catalog and requires a kebab-matching
row for each visible property. Hidden properties are skipped by reading the
catalog's own `hidden` flag rather than a second list here, so this test and the
generator cannot disagree about which options reach the command line. The second
test requires a non-empty tool description, which is the one-line summary
`uloop list` prints.

The kebab rule is duplicated from cli/common/tooldocs on purpose: it has to run on
both sides of the language boundary, and a divergence is caught from either
direction. Table parsing here is smaller than the Go parser - it locates the table
and reads its first column, never a description - so the duplicated understanding
of the file format is limited to what a missing row depends on.

The registry's test double moves out of DefaultToolsCatalogDriftTests so both
guards share it.
Nothing checked that the committed catalog still matched the tables it is
generated from, so a skill edit without a regeneration would ship help text that
disagrees with the documentation an agent reads. The step runs the generator in
check mode, which reports the mismatch and names the script that fixes it without
writing anything.

The repository root is passed explicitly because the step runs inside the module
directory, where the catalog's relative path does not resolve.
Forgetting to regenerate the catalog after editing a skill table is caught by CI,
but only after a push, which costs a round trip. The hook regenerates it whenever a
skill file is staged and adds the result to the same commit, so the mistake stops
being possible to make locally. A table that disagrees with its schema fails the
generator and blocks the commit, which is where that conflict is cheapest to fix.

The hook was never wired up (core.hooksPath is unset in a fresh clone), and wiring
it as it stood would have run the full Go check - lint, tests and a binary rebuild -
on every commit touching Go. It now runs only gofmt and go vet, seconds rather than
minutes; the full check stays where it was, in PR preparation and CI. The one-line
opt-in and the catalog rule are documented for agents, who read that file every
session.
The embedded catalog was classified with contract.json as a release-please stamp
target, so a change to it counted as no release input at all. That was true while
the descriptions were hand-edited rarely; now that the catalog is generated from
the skill tables, a pull request that improves a tool's help text and nothing else
would have passed the trigger guard and never reached a binary - the improved text
would sit in the repository and never arrive on anyone's machine.

The catalog now counts as a shared release input for both binaries, which is what
it is: `//go:embed` compiles it into each one. contract.json stays excluded, since
release-please writes it. The stamp script's file selection is meant to mirror the
guard, so it moves in step, and a case there proves the catalog reaches the stamps.
The glossary defined a skill as instructions for an agent. It is now also where the
tool and parameter descriptions the CLI prints come from, read at render time and
compiled into the embedded catalog. Naming that in the definition is what keeps
"edit the description in the skill" discoverable from the vocabulary rather than
only from the code.
@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 8ac9cf9f-c7fc-46a1-98d0-7fbfc3132bd5

📥 Commits

Reviewing files that changed from the base of the PR and between 0095dfc and 83d5909.

⛔ Files ignored due to path filters (1)
  • .husky/pre-commit is excluded by none and included by none
📒 Files selected for processing (26)
  • .agents/skills/uloop-control-play-mode/SKILL.md
  • .agents/skills/uloop-record-input/SKILL.md
  • .agents/skills/uloop-replay-input/SKILL.md
  • .agents/skills/uloop-screenshot/SKILL.md
  • .agents/skills/uloop-simulate-keyboard/SKILL.md
  • .agents/skills/uloop-simulate-mouse-input/SKILL.md
  • .agents/skills/uloop-simulate-mouse-ui/SKILL.md
  • .claude/skills/uloop-control-play-mode/SKILL.md
  • .claude/skills/uloop-record-input/SKILL.md
  • .claude/skills/uloop-replay-input/SKILL.md
  • .claude/skills/uloop-screenshot/SKILL.md
  • .claude/skills/uloop-simulate-keyboard/SKILL.md
  • .claude/skills/uloop-simulate-mouse-input/SKILL.md
  • .claude/skills/uloop-simulate-mouse-ui/SKILL.md
  • Assets/Tests/Editor/SkillParameterTableCoverageTests.cs
  • Packages/src/Editor/FirstPartyTools/ControlPlayMode/Skill/SKILL.md
  • Packages/src/Editor/FirstPartyTools/RecordInput/Skill/SKILL.md
  • Packages/src/Editor/FirstPartyTools/ReplayInput/Skill/SKILL.md
  • Packages/src/Editor/FirstPartyTools/Screenshot/Skill/SKILL.md
  • Packages/src/Editor/FirstPartyTools/SimulateKeyboard/Skill/SKILL.md
  • Packages/src/Editor/FirstPartyTools/SimulateMouseInput/Skill/SKILL.md
  • Packages/src/Editor/FirstPartyTools/SimulateMouseUi/Skill/SKILL.md
  • cli/common/skilldocs/parse.go
  • cli/common/tooldocs/tool_option_help_test.go
  • cli/common/tools/default-tools.json
  • cli/dispatcher/internal/dispatcher/command_help_skill_docs_test.go

📝 Walkthrough

Walkthrough

This PR makes SKILL.md the runtime and generated source for CLI tool descriptions. It adds skill discovery and parsing, applies installed documentation to help and list output, regenerates the embedded catalog with drift checks, and connects catalog changes to CI and release-input stamping.

Changes

Skill documentation and parsing

Layer / File(s) Summary
Skill documentation tables
.agents/skills/*, .claude/skills/*, Packages/src/Editor/.../SKILL.md, docs/glossary.md
Updates parameter tables, tool prerequisites, command guidance, and generated-catalog documentation across all skill files.
Skilldocs parser
cli/common/skilldocs/parse.go, cli/common/skilldocs/parse_test.go
Parses single- and multi-tool SKILL.md markdown, extracts frontmatter, parameter tables, and normalizes escaped syntax; tolerates CRLF, BOM, and missing tables.
Skilldocs discovery
cli/common/skilldocs/discover.go, cli/common/skilldocs/skill_docs.go
Runtime loading of skill files from installed packages, with vibe-log fallback warnings when skills are missing or unreadable.
Skilldocs application
cli/common/skilldocs/apply.go, cli/common/skilldocs/apply_test.go
Applies parsed skill descriptions to tool definitions and catalogs, mapping schema properties to CLI option names and respecting absence of skills.
Tool schema provenance
cli/common/tools/types.go, cli/common/tools/catalog.go, cli/common/tools/description_fallback.go
Adds SkillSourcedDescription field to track description origin, enriches embedded catalogs with provenance markers, and preserves source tracking in fallback paths.
Help and list integration
cli/dispatcher/internal/dispatcher/command_help.go, cli/dispatcher/internal/dispatcher/run_help.go, cli/project-runner/internal/projectrunner/list_output.go, cli/common/tooldocs/tool_option_help.go
Routes help and list output through skilldocs.ApplyToTool / ApplyToCatalog, preserves skill-sourced negated-boolean descriptions, and applies project-root-aware documentation.
Catalog generation and validation
cli/release-automation/internal/automation/tool_docs_sync.go, cli/release-automation/internal/automation/tool_docs_json_editor.go
Generates embedded tool catalog with byte-preserving JSON editing, validates schema/table alignment, reports undocumented and unknown parameter row drift.
Catalog sync testing
cli/release-automation/internal/automation/tool_docs_sync_test.go
Validates generation idempotence, detects schema/table mismatches, ignores hidden properties, and tests check-only and write modes.
Help output testing
cli/dispatcher/internal/dispatcher/command_help_skill_docs_test.go, cli/project-runner/internal/projectrunner/list_output_test.go, cli/common/tooldocs/tool_option_help_test.go
Verifies help text sourcing from skills, negated-boolean preservation, embedded fallbacks, and list output description application.
Parameter table coverage
Assets/Tests/Editor/SkillParameterTableCoverageTests.cs
Unity test that enforces every non-hidden schema property has a skill parameter table row and every catalog tool has a skill description.
Release automation integration
cli/release-automation/internal/automation/release_trigger_guard.go, cli/release-automation/internal/automation/release_trigger_guard_test.go, scripts/stamp-release-inputs.sh, scripts/sync-tool-docs.sh, scripts/test-stamp-release-inputs.sh
Extends release-trigger analysis to include skilldocs package and catalog as shared release inputs; adds CI drift check; updates stamping tests for catalog changes.
CI and workflow
.github/workflows/build-and-test.yml, AGENTS.md, docs/glossary.md, cli/dispatcher/shared-inputs-stamp.json, cli/project-runner/shared-inputs-stamp.json
Adds sync-tool-docs --check to build workflow, documents generated-catalog ownership, updates glossary, and updates release-input hashes.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Skill as SKILL.md
  participant Parser as skilldocs/parse
  participant Discover as skilldocs/discover
  participant Help as Help/List
  participant Sync as sync-tool-docs
  participant Catalog as default-tools.json
  Skill->>Parser: Parse parameter tables
  Parser->>Discover: Return tool docs
  Discover->>Help: Load and apply at runtime
  Help->>Help: Render with skill text
  Skill->>Sync: Extract descriptions
  Sync->>Catalog: Replace via JSON editor
  Sync->>Sync: Validate schema/table drift
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 62.20% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main change: rendering tool help from skill parameter tables.
Description check ✅ Passed The description is directly related to the changeset and accurately describes the help text sync and validation work.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/tool-docs-skill-read

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
cli/project-runner/internal/projectrunner/list_output_test.go (1)

251-279: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicated skill-fixture test helper across two packages. writeSkillFixtureProject and writeSkillDocsFixturePackage write the identical fake uloop package (package.json manifest + simulate-keyboard SKILL.md with the same frontmatter/table) purely to test that installed-skill descriptions win over embedded ones; if the skill fixture format ever needs to change, both copies must be updated in lockstep.

  • cli/project-runner/internal/projectrunner/list_output_test.go#L251-L279: extract this logic into a small shared internal test-support package (e.g. under cli/common/skilldocs or a new testsupport package) exposing a WriteSkillFixturePackage(t, root, durationDescription) helper, and have this file call it.
  • cli/dispatcher/internal/dispatcher/command_help_skill_docs_test.go#L82-L108: replace writeSkillDocsFixturePackage with a call to the same shared helper instead of maintaining a second copy.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cli/project-runner/internal/projectrunner/list_output_test.go` around lines
251 - 279, The skill fixture creation logic is duplicated across two test
packages. Extract the shared package-manifest and simulate-keyboard SKILL.md
setup from writeSkillFixtureProject into a shared test-support helper such as
WriteSkillFixturePackage(t, root, durationDescription), then replace
writeSkillFixtureProject in
cli/project-runner/internal/projectrunner/list_output_test.go:251-279 and
writeSkillDocsFixturePackage in
cli/dispatcher/internal/dispatcher/command_help_skill_docs_test.go:82-108 with
calls to that helper; both sites require direct changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/glossary.md`:
- Around line 94-98: Update the glossary passage describing description sources
to qualify the “nowhere else” claim: skill parameter tables remain authoritative
for skill-backed tools, while fallback metadata remains authoritative for tools
without skills. Preserve the existing explanation of --help, uloop list, and the
generated embedded catalog.

---

Nitpick comments:
In `@cli/project-runner/internal/projectrunner/list_output_test.go`:
- Around line 251-279: The skill fixture creation logic is duplicated across two
test packages. Extract the shared package-manifest and simulate-keyboard
SKILL.md setup from writeSkillFixtureProject into a shared test-support helper
such as WriteSkillFixturePackage(t, root, durationDescription), then replace
writeSkillFixtureProject in
cli/project-runner/internal/projectrunner/list_output_test.go:251-279 and
writeSkillDocsFixturePackage in
cli/dispatcher/internal/dispatcher/command_help_skill_docs_test.go:82-108 with
calls to that helper; both sites require direct changes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 72ec4086-35a1-4104-902b-7e7e6961ca3e

📥 Commits

Reviewing files that changed from the base of the PR and between d4fcf16 and 0095dfc.

⛔ Files ignored due to path filters (3)
  • .husky/pre-commit is excluded by none and included by none
  • Assets/Tests/Editor/AlwaysEnabledToolSettingsPort.cs.meta is excluded by none and included by none
  • Assets/Tests/Editor/SkillParameterTableCoverageTests.cs.meta is excluded by none and included by none
📒 Files selected for processing (55)
  • .agents/skills/uloop-compile/SKILL.md
  • .agents/skills/uloop-execute-dynamic-code/SKILL.md
  • .agents/skills/uloop-pause-point/SKILL.md
  • .agents/skills/uloop-record-input/SKILL.md
  • .agents/skills/uloop-simulate-keyboard/SKILL.md
  • .agents/skills/uloop-simulate-mouse-input/SKILL.md
  • .claude/skills/uloop-compile/SKILL.md
  • .claude/skills/uloop-execute-dynamic-code/SKILL.md
  • .claude/skills/uloop-pause-point/SKILL.md
  • .claude/skills/uloop-record-input/SKILL.md
  • .claude/skills/uloop-simulate-keyboard/SKILL.md
  • .claude/skills/uloop-simulate-mouse-input/SKILL.md
  • .github/workflows/build-and-test.yml
  • AGENTS.md
  • Assets/Tests/Editor/AlwaysEnabledToolSettingsPort.cs
  • Assets/Tests/Editor/DefaultToolsCatalogDriftTests.cs
  • Assets/Tests/Editor/SkillParameterTableCoverageTests.cs
  • Packages/src/Editor/CliOnlyTools~/PausePoint/Skill/SKILL.md
  • Packages/src/Editor/FirstPartyTools/Compile/Skill/SKILL.md
  • Packages/src/Editor/FirstPartyTools/ExecuteDynamicCode/Skill/SKILL.md
  • Packages/src/Editor/FirstPartyTools/RecordInput/Skill/SKILL.md
  • Packages/src/Editor/FirstPartyTools/SimulateKeyboard/Skill/SKILL.md
  • Packages/src/Editor/FirstPartyTools/SimulateMouseInput/Skill/SKILL.md
  • cli/common/skilldocs/apply.go
  • cli/common/skilldocs/apply_test.go
  • cli/common/skilldocs/discover.go
  • cli/common/skilldocs/parse.go
  • cli/common/skilldocs/parse_test.go
  • cli/common/skilldocs/skill_docs.go
  • cli/common/tooldocs/tool_option_help.go
  • cli/common/tooldocs/tool_option_help_test.go
  • cli/common/tools/catalog.go
  • cli/common/tools/default-tools.json
  • cli/common/tools/description_fallback.go
  • cli/common/tools/description_fallback_test.go
  • cli/common/tools/types.go
  • cli/dispatcher/internal/dispatcher/command_help.go
  • cli/dispatcher/internal/dispatcher/command_help_skill_docs_test.go
  • cli/dispatcher/internal/dispatcher/help_test.go
  • cli/dispatcher/internal/dispatcher/run_help.go
  • cli/dispatcher/shared-inputs-stamp.json
  • cli/project-runner/internal/projectrunner/list_output.go
  • cli/project-runner/internal/projectrunner/list_output_test.go
  • cli/project-runner/internal/projectrunner/run.go
  • cli/project-runner/shared-inputs-stamp.json
  • cli/release-automation/cmd/sync-tool-docs/main.go
  • cli/release-automation/internal/automation/release_trigger_guard.go
  • cli/release-automation/internal/automation/release_trigger_guard_test.go
  • cli/release-automation/internal/automation/tool_docs_json_editor.go
  • cli/release-automation/internal/automation/tool_docs_sync.go
  • cli/release-automation/internal/automation/tool_docs_sync_test.go
  • docs/glossary.md
  • scripts/stamp-release-inputs.sh
  • scripts/sync-tool-docs.sh
  • scripts/test-stamp-release-inputs.sh
💤 Files with no reviewable changes (1)
  • Assets/Tests/Editor/DefaultToolsCatalogDriftTests.cs

Comment thread docs/glossary.md
Comment on lines +94 to +98
A skill is also the single source of truth for the tool and parameter descriptions the CLI
prints. `--help` and `uloop list` read the parameter table out of the installed package's
skill at render time, and the embedded catalog (`cli/common/tools/default-tools.json`) is
generated from those same tables. Descriptions are therefore edited in the skill and nowhere
else.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Qualify the “nowhere else” source-of-truth claim.

Fallback descriptions remain supported for tools without skills, so this wording incorrectly implies that every description must be edited only in a skill. Clarify that skill tables own skill-backed descriptions while fallback metadata remains authoritative for tools without skills.

Proposed wording
-Descriptions are therefore edited in the skill and nowhere else.
+Skill-backed descriptions are edited in the skill and nowhere else; tools
+without skills continue to use their fallback descriptions.

This follows the PR objective to preserve fallback descriptions for tools without skills.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
A skill is also the single source of truth for the tool and parameter descriptions the CLI
prints. `--help` and `uloop list` read the parameter table out of the installed package's
skill at render time, and the embedded catalog (`cli/common/tools/default-tools.json`) is
generated from those same tables. Descriptions are therefore edited in the skill and nowhere
else.
A skill is also the single source of truth for the tool and parameter descriptions the CLI
prints. `--help` and `uloop list` read the parameter table out of the installed package's
skill at render time, and the embedded catalog (`cli/common/tools/default-tools.json`) is
generated from those same tables. Skill-backed descriptions are edited in the skill and nowhere
else; tools without skills continue to use their fallback descriptions.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/glossary.md` around lines 94 - 98, Update the glossary passage
describing description sources to qualify the “nowhere else” claim: skill
parameter tables remain authoritative for skill-backed tools, while fallback
metadata remains authoritative for tools without skills. Preserve the existing
explanation of --help, uloop list, and the generated embedded catalog.

hatayama added 4 commits July 27, 2026 09:43
Generating descriptions from the tables made the tables authoritative, and fifteen
cells were thinner than the catalog text they replaced - so help and `uloop list`
lost information that had been there.

What went missing was the part a caller cannot guess. Every enum cell had been
reduced to a bare list of member names: `Press`, `KeyDown`, `KeyUp`, `ReleaseAll`
says nothing about what any of them do, and in particular nothing about
`ReleaseAll` being the way out of inconsistent key state after a pause point
interrupts PlayMode. The same happened to simulate-mouse-input, simulate-mouse-ui,
replay-input, record-input and control-play-mode, where `Step`, `Status` and
`Resume` had no explanation at all. Elsewhere it was the fact behind the number or
the flag: which direction a positive `--scroll-y` scrolls, that drag origins are
top-left, that rendering screenshots return the formula for converting raw pixels,
that `--annotate-elements` also returns element metadata.

Each cell now carries what its catalog counterpart carried, so the regenerated
descriptions read the same as before this change for the reader of `--help` while
staying the single place the text is edited.
Two ways the hook could produce a commit nobody wrote:

Regenerating overwrites the catalog, so an unstaged hand edit to it was swept into
the commit as though the generator had produced it. The hook now refuses to run in
that state and says what to do, because that edit is lost either way - the next run
overwrites it - and losing it silently inside someone else's commit is the worse of
the two.

The generator reads the working tree, so staging a skill file with `git add -p`
produced a catalog describing text the commit does not contain. A partially staged
skill file now stops the commit rather than being resolved by guesswork about which
version was meant.

The skill-file pattern also no longer names the two CLI-only skill directories that
happen to exist today; the reader it feeds scans all of them.
Deleting either assignment - the one in the skill reader or the one that carries the
flag through the embedded fallback - left every test green, so nothing was holding
the behaviour they exist for: a negated boolean printing its documented wording
instead of a synthesized "Disable <name>".

One test covers each path. The reader's test documents a property the embedded
catalog does not know, so only the skill can describe it; without the assignment the
help output falls back to the synthesized summary. The fallback's test starts from
Unity's placeholder and checks the description it picks up survives the same way.
The parser normalized line endings and a BOM once for the table and then handed the
raw file to the frontmatter reader, so a file containing lone CRs would have been
understood two different ways by one function. Git never writes that, but "the
normalization happens in one place" is this feature's own rule, and the frontmatter
path was outside it.

The C# guard's table splitter gains a note on why it does not resolve the "\|"
escape: it reads only the first column. Reading a description there needs the same
handling the Go splitter has.
@hatayama
hatayama merged commit 7b020ec into feature/cli-discoverability-integration Jul 27, 2026
1 of 2 checks passed
@hatayama
hatayama deleted the feat/tool-docs-skill-read branch July 27, 2026 00:46
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