feat(cli): add structlint suggest — propose config diffs and file moves#19
Merged
Conversation
Runs the same engine as validate, then maps each violation to a concrete
proposal: config addition (rendered as a unified diff), file move (as a
git mv command), file create, or a review note. Print-only, exit 0 even
with proposals — this is advisory; violation gating is validate's job.
Spec: docs/specs/010-suggest.md.
Files:
- internal/suggest/proposals.go — Proposal + Report types; Kind enum;
JSON tags for the v1 contract consumed by editors and agents.
- internal/suggest/suggest.go — Analyze(cfg, configPath, root) runs the
validator (silent) and turns violations into proposals via a per-code
mapping table. disallowed_* codes NEVER produce a loosening proposal
— they get a note that says "the rule is deliberate".
- internal/suggest/configdiff.go — line-level insertion into the original
config text (never re-marshal, preserves comments/ordering/quoting)
plus a small unified-diff renderer since we only ever INSERT lines.
- internal/cli/suggest.go — flag parsing, text/json rendering.
Uses spec 009's infer generalizer indirectly (via reused validator.Tree
paths) for glob generalization.
JSON v1 contract (versioned from day one):
{version:1, configPath, proposals:[{kind, section, value | from/to/command
| path, reason, paths}], configDiff}
Tests (test/suggest_test.go, binary-based):
- JSON contract version 1
- per-code proposals: config_add for unallowed_*, move for placement,
note for disallowed_*
- disallowed never loosened (no proposal touches disallowed section)
- round-trip: pipe configDiff through patch(1), re-run validate, exit 0
(the primary property that agents/editors depend on)
- exit 0 with proposals present
- exit non-zero on operational error (no config)
- move emits git mv <from> <to>
Docs: cli-reference.md documents the command, JSON contract, and the
suggest → patch → git mv → validate fix loop.
StructLint — All checks passed129 rules validated against
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Design highlights
The fix loop
```bash
structlint suggest --format json > /tmp/report.json
jq -r .configDiff /tmp/report.json | patch -p1
jq -r '.proposals[] | select(.kind=="move") | .command' /tmp/report.json | sh
structlint validate
```
Test plan