Repository navigation
Make sure AGENTS.md template is synced & polishes - #13
Merged
Merged
Conversation
Separate two claims that were both being carried by `=trivial`: a *risk*
claim ("too small to hide behavior") and an *epistemic* claim ("intent is
intrinsic to the surface form"). In practice `=trivial` was stretched onto
substantial code — an 11-line context struct, a 163-line test module —
where the item is not small but its intent is self-evident. This is the
review-action a reviewer actually wanted but had no label for.
Add `=self-doc` for the epistemic case, with a strict test that resists the
"self-documenting" excuse: a competent-but-domain-stranger reader holding
only name, signature, and durable co-located context must recover every
property any observer could rely on, including non-value-domain effects
(timing, resources, termination, information flow). The test is an open
observer counterfactual, not a finite effect checklist, and side effects
are presumptively disqualifying with a discharge (not assert) obligation.
Also document the derivative-item rule: items whose whole purpose is to
exercise/assert another specced item (chiefly tests) carry no independent
intent and should be excluded from inference entirely — no entry, not a
lighter sentinel — since specifying test intent is circular with adversarial
test generation.
Record the threat-model boundary as an explicit non-goal: 立意 surfaces
hidden intent but does not verify the honesty of intent deliberately
misrepresented via non-co-located or runtime-controlled state.
Original prompt:
> [multi-turn discussion, see session] Assess integrating 立意 into agentic
> scaffolds; then: whether `=per-se`/`=self-doc` should complement `=trivial`;
> survey the repo's `=trivial` uses; settle the reference reader, durable
> context, observer/effect closure, and threat-model boundary; then make each
> change to the spec, the AGENTS.md edits, and the implementation, in commits.
AI-assisted-by: Claude Opus 4.8 (OpenCode)
Signed-off-by: WANG Xuerui <[email protected]>
Update the AGENTS.md intent-spec template (the deliverable downstream repos adopt) to match the design doc. Rule 1 gains the `=self-doc` sentinel with its strict test — a competent-but-domain-stranger reader, durable co-located context only, an open observer counterfactual over non-value-domain effects, side effects presumptively disqualifying, and a discharge (not assert) obligation. Rule 8 gains the derivative-item exclusion (no entry for items whose whole purpose is to exercise another specced item) and extends the `@liyi:nontrivial` conflict to `=self-doc`. The embedded schema `intent` description lists the new sentinel. Original prompt: > [multi-turn discussion, see session] ... then make each change to the spec, > the AGENTS.md edits, and the implementation, in commits. AI-assisted-by: Claude Opus 4.8 (OpenCode) Signed-off-by: WANG Xuerui <[email protected]>
Implement the =self-doc sentinel defined in the design doc and template. check_trivial_ignore now recognizes both "=trivial" and "=self-doc" in the sidecar: each emits an info-level Trivial diagnostic, is not flagged stale, is not counted unreviewed on its own, and is skipped by adversarial testing; an in-span @liyi:nontrivial conflicts with either (ConflictingTriviality error), which is what forbids a side-effecting item from being filed as self-documenting. format_github_actions treats =self-doc as a sentinel so its value is not appended as intent prose. The schema intent description lists the new sentinel. A self_doc_sidecar fixture and golden test cover the three cases: a plain enum, a non-trivial-but-self-doc recursive helper (the case =trivial could not honestly cover), and a @liyi:nontrivial conflict on side-effecting remainder logic. The check.rs and diagnostics.rs behavior changes touch two reviewed items (check_trivial_ignore, format_github_actions); their intent text is updated to mention =self-doc, "reviewed" is unset, and source_hash dropped per the staleness rules, leaving them for human re-approval. Original prompt: > [multi-turn discussion, see session] ... then make each change to the spec, > the AGENTS.md edits, and the implementation, in commits. AI-assisted-by: Claude Opus 4.8 (OpenCode) Signed-off-by: WANG Xuerui <[email protected]>
The =self-doc sentinel (added in 5d95f88 and the follow-up commits afb0a8e, f19e585, 38f207b) separates two claims that =trivial previously conflated: a risk claim ("too small to hide behavior") from an epistemic claim ("intent is intrinsic to the surface form"). Nine pre-existing =trivial entries had been stretched onto substantial items — data structs and a context bundle, an enum, and multi-line search helpers — where =trivial was a lie about size and =self-doc is the honest label. Each affected spec sets "reviewed" to false (intent changed, source unchanged), leaving it for human re-approval per the staleness rules. Genuinely tiny items keep =trivial: one-line consts/statics, a one-line function body, and the declarative CI trigger block. Derivative test specs are dropped in a follow-up commit. Original prompt: > please survey the pre-existing `=trivial` intents and change to `=self-doc` or re-infer each, for any such intent no longer conforming to the current revised standard (read `git diff 5d95f88` for the exact changes). > please commit. AI-assisted-by: DeepSeek V4.1 Flash (OpenCode) Signed-off-by: WANG Xuerui <[email protected]>
The revised standard excludes derivative items from inference entirely: an item whose whole purpose is to exercise or assert an already-specced item adds no invariant of its own, so a per-item entry creates a fake review burden, a hash-tracking liability, and circularity (adversarial tests are generated from reviewed intent). Remove the sidecar entries for the context.rs `mod tests` module, its `write` helper, and all nine test functions; the end state for a derivative item is no entry, not a lighter =trivial or =self-doc row. Original prompt: > please survey the pre-existing `=trivial` intents and change to `=self-doc` or re-infer each, for any such intent no longer conforming to the current revised standard (read `git diff 5d95f88` for the exact changes). > please commit. AI-assisted-by: DeepSeek V4.1 Flash (OpenCode) Signed-off-by: WANG Xuerui <[email protected]>
Two "Linter behavior" paragraphs claimed sidecar `=trivial`/`=self-doc` specs are "not stale" and "not counted as unreviewed". Both claims are false: `check_item_hash` and `check_review_status` have no sentinel case, so a sentinel spec is an ordinary tracked spec — unsetting `reviewed` surfaces it as unreviewed, and a source change marks it stale. The rest of the design already agrees (the reviewer-responsibility table gives a review action per sentinel, `=doc` is explicitly staleness-tracked, and the level `all` summary lists trivial/unreviewed/stale together). Correct the doc, not the code: everything gets reviewed, sentinels included. Original prompt: > actually isn't the point "every intent should get reviewed" i.e. "trivial/self-doc sentinels should be reviewed too"? the doc has a table describing reviewer responsibilities -- what to prove when encountering different sentinels, so the implication has always been that they are to human-approve EVERYTHING. so any text implying otherwise should get corrected. and regarding triviality of "single expressions", maybe modify to "simple expressions", to disqualify complex ones like `machine == EM_FOO && (bar_count <= X || should_baz && quux (state->xxx, yyy) && ...`. what do you think? AI-assisted-by: DeepSeek V4.1 Flash (OpenCode) Signed-off-by: WANG Xuerui <[email protected]>
"=trivial" is a risk claim (too small to hide behavior), but the docs
defined the boundary only as "simple getters, one-line wrappers" — which
conflates size with syntax. A body that is a single expression is not
automatically trivial: a compound boolean guard whose operand order,
short-circuit evaluation, nested calls, or cost are load-bearing hides
real behavior and belongs in prose. State that a body must be a *simple*
expression, not merely one expression, and note that body line count is a
heuristic rather than the criterion. Also fix the `@liyi:trivial` marker
definition, which described the =self-doc epistemic claim ("intent is
self-evident from its signature") rather than the =trivial risk claim.
Original prompt:
> actually isn't the point "every intent should get reviewed" i.e. "trivial/self-doc sentinels should be reviewed too"? the doc has a table describing reviewer responsibilities -- what to prove when encountering different sentinels, so the implication has always been that they are to human-approve EVERYTHING. so any text implying otherwise should get corrected. and regarding triviality of "single expressions", maybe modify to "simple expressions", to disqualify complex ones like `machine == EM_FOO && (bar_count <= X || should_baz && quux (state->xxx, yyy) && ...`. what do you think?
AI-assisted-by: DeepSeek V4.1 Flash (OpenCode)
Signed-off-by: WANG Xuerui <[email protected]>
The =self-doc section cited "the 163-line test module" as its canonical example of a substantial-but-self-evident item. That contradicts the derivative-item rule added in the same change: a test whose whole purpose is to exercise or assert an already-specced item gets no sidecar entry at all, so it is never filed as =self-doc. Replace the example with a data-only enum (RecoveryMethod), which =self-doc legitimately covers. Original prompt: > actually isn't the point "every intent should get reviewed" i.e. "trivial/self-doc sentinels should be reviewed too"? the doc has a table describing reviewer responsibilities -- what to prove when encountering different sentinels, so the implication has always been that they are to human-approve EVERYTHING. so any text implying otherwise should get corrected. and regarding triviality of "single expressions", maybe modify to "simple expressions", to disqualify complex ones like `machine == EM_FOO && (bar_count <= X || should_baz && quux (state->xxx, yyy) && ...`. what do you think? AI-assisted-by: DeepSeek V4.1 Flash (OpenCode) Signed-off-by: WANG Xuerui <[email protected]>
Rule 6 authorized adversarial test generation from any item with `"reviewed": true`. Once sentinel specs are properly reviewed (they are ordinary tracked specs — only their attack surface differs), that clause would sweep `=trivial`/`=self-doc` items into test generation, contradicting the design's "skipped by the adversarial testing agent". State the exclusion explicitly: sentinels carry no agent-authored intent for a second model to attack. Applied to the AGENTS.md template and the design doc's minimal-instruction mirror. Original prompt: > actually isn't the point "every intent should get reviewed" i.e. "trivial/self-doc sentinels should be reviewed too"? the doc has a table describing reviewer responsibilities -- what to prove when encountering different sentinels, so the implication has always been that they are to human-approve EVERYTHING. so any text implying otherwise should get corrected. and regarding triviality of "single expressions", maybe modify to "simple expressions", to disqualify complex ones like `machine == EM_FOO && (bar_count <= X || should_baz && quux (state->xxx, yyy) && ...`. what do you think? AI-assisted-by: DeepSeek V4.1 Flash (OpenCode) Signed-off-by: WANG Xuerui <[email protected]>
Agents can hit genuine conflicts between normative rules (or ambiguities the convention leaves open) where guessing silently produces the wrong deliverable. Add an explicit escalation preference: name the conflict, don't guess; ask once with candidate resolutions if a human is reachable; otherwise take the conservative reading, leave affected specs unreviewed, and surface the conflict. Scope it so it is not a license to stall on judgment the standard delegates (e.g. the =self-doc observer test). Added to the AGENTS.md template and the design doc's agent-skill section, both after the tracked requirement blocks. Original prompt: > okay, and do you think it would be worth it to add conflict resolution preference (when several liyi agent rules appear to be in conflict, don't ever guess, ask the user) and whatever else to the AGENTS.md instructions, per your experience in this session? > ok, make the changes, batched by semantic change i.e. each commit makes one semantic change to the docs & related code. the conflict rule belongs to its own commit as well. AI-assisted-by: DeepSeek V4.1 Flash (OpenCode) Signed-off-by: WANG Xuerui <[email protected]>
Rule 10 told agents that after unsetting `reviewed` and deleting `source_hash`, the human would run `liyi check --fix` or `liyi approve --rehash`. There is no `--rehash` flag: the `approve` subcommand only defines `--yes`, `--dry-run`, `--item`, `--unreviewed-only`, `--stale-only`, and `--req-only`, and the design doc's `liyi approve` flag list has no such option either. `liyi approve` already rehashes a stale-reviewed item when the human confirms it, so drop the bogus flag and point at the real command. Root cause: the never-compute-hashes paragraph was written directly into AGENTS.md without a matching design-doc review, so the invented flag was never checked against the CLI. Original prompt: > check if the current `liyi:template` section in `AGENTS.md` differs > from `liyi-design.md` prescription, fix `AGENTS.md` and commit if any > inconsistency is found. > Bidirectional sync -- fix `--rehash` in a commit, then update the > design doc in another syncing commit. I was implying the design doc > leads AGENTS.md but apparently this is false -- fixing the trailing doc > is the right call. AI-assisted-by: DeepSeek V4.1 Flash (OpenCode) Signed-off-by: WANG Xuerui <[email protected]>
The design doc reproduces the AGENTS.md behavioral rules and carries the canonical `.liyi.jsonc` JSON Schema, but both had fallen behind the template: - Reproduced rules 1, 2, 8, 10, and 11 were the pre-`=self-doc` text. Rule 1 lacked the `=self-doc` sentinel and its observer test plus the reviewed-unset warning; rule 8 lacked the `@liyi:nontrivial` / `"=self-doc"` conflict and the derivative-item exclusion; rule 10 lacked the never-compute-hashes paragraph; rule 11 still said "consume the `--prompt` output" instead of "prefer `--prompt` for structured JSON". Rule 2 was the pre-`@liyi:note` v0.2 wording. - The Appendix schema's `intent` description enumerated only `=doc` and `=trivial`, omitting `=self-doc`, so it disagreed with both the template's embedded schema and `schema/liyi.schema.json`. Root cause: later changes landed in AGENTS.md (rule 1/8 in f19e585, the never-compute-hashes paragraph in c4fb25c, rule 11 in 72db3ff) and in `schema/liyi.schema.json` (38f207b) without the design doc's reproduced copies being updated, because only the changelog narrative was treated as the spec while the reproduced rules and appendix were not. Original prompt: > check if the current `liyi:template` section in `AGENTS.md` differs > from `liyi-design.md` prescription, fix `AGENTS.md` and commit if any > inconsistency is found. > Bidirectional sync -- fix `--rehash` in a commit, then update the > design doc in another syncing commit. I was implying the design doc > leads AGENTS.md but apparently this is false -- fixing the trailing doc > is the right call. AI-assisted-by: DeepSeek V4.1 Flash (OpenCode) Signed-off-by: WANG Xuerui <[email protected]>
The design doc described the AGENTS.md payload as "10 behavioral rules" in four places, but the reproduced instruction has eleven rules and the same document elsewhere says "the 11 behavioral rules" / "the full 11-rule protocol". The count is incidental, so drop the exact numbers rather than renumber (and rewrite the MUST/SHOULD split's "these 3 things" / "these 8 things" to avoid implying a count). Original prompt: > please fix the rule count mismatch (preferably don't spell out exact > numbers if at all possible), and also the "key principles" -- make the > subtitle more specific, then sync it to AGENTS.md. AI-assisted-by: DeepSeek V4.1 Flash (OpenCode) Signed-off-by: WANG Xuerui <[email protected]>
The design doc's `### Key principles` section (adversarial not confirmatory, spec is the referee, model diversity, never modify source logic) had no counterpart in the AGENTS.md template, even though its sibling `### Resolving rule conflicts` was already synced there. Rename the heading to `### Key principles of the intent protocol` so it is specific about what it governs, and copy the section verbatim into the AGENTS.md template between the behavioral rules and `### Resolving rule conflicts`, matching the design doc's ordering. Original prompt: > please fix the rule count mismatch (preferably don't spell out exact > numbers if at all possible), and also the "key principles" -- make the > subtitle more specific, then sync it to AGENTS.md. AI-assisted-by: DeepSeek V4.1 Flash (OpenCode) Signed-off-by: WANG Xuerui <[email protected]>
AGENTS.md is the source of truth for the agent instruction — `liyi init` ships the block between the `<!-- liyi:template:start -->` and `<!-- liyi:template:end -->` markers — while docs/liyi-design.md reproduces the behavioral rules, key principles, and the `.liyi.jsonc` schema appendix. Nothing kept the two copies in sync, so they have silently drifted before: the `=self-doc` sentinel reached the template and `schema/liyi.schema.json` but not the design doc's reproduced rules or appendix. Add scripts/check-template-sync.py, which extracts the reproduced regions from both files and fails with a unified diff when they diverge. The sidecar schema is compared as parsed JSON, so the template's `\u0040` quine escape and the doc's literal `@` are treated as equal. "Resolving rule conflicts" is intentionally skipped (the doc states it as prose, the template as a numbered list) as is the triage schema (no design-doc counterpart). Wire the check into `make lint`, and mirror it in `make lint-short` so the commit gate enforces it. Original prompt: > please add that consistency check to both the commit gate and CI! AI-assisted-by: DeepSeek V4.1 Flash (OpenCode) Signed-off-by: WANG Xuerui <[email protected]>
List the new agent-template sync check among the `make lint` gates in AGENTS.md, CONTRIBUTING.md, and both contributing guides (EN/ZH). Original prompt: > please add that consistency check to both the commit gate and CI! AI-assisted-by: DeepSeek V4.1 Flash (OpenCode) Signed-off-by: WANG Xuerui <[email protected]>
Add a `template-sync` job that runs scripts/check-template-sync.py, and record the job in the workflow's sidecar so `liyi check` stays green. Original prompt: > please add that consistency check to both the commit gate and CI! AI-assisted-by: DeepSeek V4.1 Flash (OpenCode) Signed-off-by: WANG Xuerui <[email protected]>
The template-sync check had to parse regions (fenced Markdown block, headings) and special-case the JSON schema, because the AGENTS.md template block — behavioral rules, key principles, conflict resolution, and both JSON schemas — was not byte-identical to the design doc's condensation: prose conflicts instead of a list, the sidecar schema in a separate appendix, the triage schema missing, and the marker escaped as `\u0040` in AGENTS.md. Make docs/liyi-design.md carry the same `<!-- liyi:template:start/end -->` block verbatim: replace the inline reproductions with a pointer to the new section and fold the schema appendix into the block (which also brings in the previously absent triage schema). Unescape the marker in AGENTS.md's embedded schema so the blocks match byte-for-byte; it sits in a fenced code block, which the scanner already skips. The check is now a plain string comparison, and `--sync` (surfaced as `make template-sync-fix`) copies the AGENTS.md block over the design doc's, so drift can be fixed instead of just reported. Sidecar consequences of the design-doc edit, resolved in the same commit to keep `liyi check` green: the `version-field-required` requirement's hash changed (its cross-reference now points at the verbatim block), and `validate_version`'s related edge was re-filled with `liyi check --fix`. Original prompt: > are you over-engineering the template check? why not reframe the > design doc so that it also features a `<!-- liyi:template -->` block, > then we can simply extract, compare and even offer to sync that? AI-assisted-by: DeepSeek V4.1 Flash (OpenCode) Signed-off-by: WANG Xuerui <[email protected]>
The `liyi:template` block started with its own `## 立意 (Intent Specs)` heading, so the design doc could not choose where the block sits without that heading dictating the outline. Move the heading outside the `<!-- liyi:template:start/end -->` markers in both files; the block now begins at "When writing or modifying code:". `liyi init` must still ship the heading, so `init_agents_md` now prepends `## 立意 (Intent Specs)` before the block when appending to or creating AGENTS.md. Its intent was updated accordingly and left unreviewed for a human to re-approve; the `init_sidecar` span shift was rehashed in the same commit. Original prompt: > Hmm, maybe the block should be *minus the section heading* to preserve > the design doc's outline. Also in another commit please make the job > `sync-template` and `check-template-sync` for better readability. AI-assisted-by: DeepSeek V4.1 Flash (OpenCode) Signed-off-by: WANG Xuerui <[email protected]>
Rename the gate from `template-sync` to `check-template-sync` and the fixer from `template-sync-fix` to `sync-template`, matching the verb-first style of `fmt-check`, `liyi-check`, and the `check-template-sync.py` script. The CI job (and its sidecar spec) is renamed to `check-template-sync` as well, and the failure hint now points at `make sync-template`. Original prompt: > Hmm, maybe the block should be *minus the section heading* to preserve > the design doc's outline. Also in another commit please make the job > `sync-template` and `check-template-sync` for better readability. AI-assisted-by: DeepSeek V4.1 Flash (OpenCode) Signed-off-by: WANG Xuerui <[email protected]>
Reconsider the previous commit's approach: instead of stripping the section heading out of both blocks and teaching `liyi init` to re-add it, keep the `## 立意 (Intent Specs)` heading inside AGENTS.md's template block — the artifact `liyi init` actually ships — and leave only the design doc's block heading-less, so the design doc's own heading still governs its outline. This reverts the `init_agents_md` special-casing (and its sidecar churn): `agents_md_block` is a pure extractor again and the shipped block stays self-contained. The template-sync check now accounts for the heading by comparing AGENTS.md's block against the design doc's block prefixed with `## 立意 (Intent Specs)`, and `make sync-template` materializes AGENTS.md from the design doc, adding the heading — the design doc is the source. Original prompt: > Oh, actually I meant: when syncing the template block from the design > doc to `AGENTS.md`, add the desired section heading in this step, so the > `liyi init` logic stays the same. When checking sync status, account for > the section heading handling. Do you think this to be better? AI-assisted-by: DeepSeek V4.1 Flash (OpenCode) Signed-off-by: WANG Xuerui <[email protected]>
This commit was authored entirely manually by me, and the sidecar for `scripts/check-template-sync.py` is also manually crafted (`liyi init` didn't surface the top-level constant I desired). Signed-off-by: WANG Xuerui <[email protected]>
`agents_md_block_extracts_valid_template` still expected the old `## 立意` section heading, but the heading was reworded to `## The 立意 (Intent Specs) design pattern for agents`. Update the assertion so the test matches the extracted block again. This is a pre-existing failure left by the manual heading refactor; it is unrelated to the Python tree_path work but blocks `make verify`. Original prompt: > Please check `git diff --cached` and add test cases for the added > items, and commit. AI-assisted-by: DeepSeek V4.1 Flash (OpenCode) Signed-off-by: WANG Xuerui <[email protected]>
The `@liyi:related` marker for HEADING was written inside a triple-quoted string, so the scanner read the closing `'''` as part of the requirement name (`agents-md-instructions-section-naming'''`), and `liyi check` failed with "related requirement not found". Make it a plain comment and correct the sidecar's related edge, then let `liyi check --fix` rehash. This is a pre-existing failure from the manually crafted sidecar; it is unrelated to the Python tree_path work but blocks `make verify`. Original prompt: > Please check `git diff --cached` and add test cases for the added > items, and commit. AI-assisted-by: DeepSeek V4.1 Flash (OpenCode) Signed-off-by: WANG Xuerui <[email protected]>
Python's tree_path config only mapped functions and classes, so module-level constants were invisible to `liyi init` and to the resolver. Register `const` for module-level `assignment` nodes, extract the name via a `python_node_name` callback that requires a plain-identifier target directly under the module root (excluding locals and attributes), and traverse the wrapping `expression_statement` as a transparent kind. Add resolve/compute/roundtrip tests for the newly sampled `TOPLEVEL_CONST`, plus a discovery test pinning that only module-level assignments become `const` items. Original prompt: > Please check `git diff --cached` and add test cases for the added > items, and commit. AI-assisted-by: DeepSeek V4.1 Flash (OpenCode) Signed-off-by: WANG Xuerui <[email protected]>
Signed-off-by: WANG Xuerui <[email protected]>
Replace the bare `<!-- liyi:template:start/end -->` markers with a
DocToc-style pragma that names the region and carries a monotonic
revision, so a downstream `AGENTS.md` can be refreshed in place by
`liyi migrate` instead of relying on `init_agents_md` matching the
section heading:
<!-- START liyi agent instructions rev. 1 -->
<!-- DON'T EDIT THIS SECTION. IT IS UPDATED ONLY BY `liyi migrate`, FROM A NEWER LIYI RELEASE. -->
...
<!-- END liyi agent instructions -->
Unlike DocToc — whose reminder tells users to re-run it after every
outline change — this block changes only when a newer Liyi release ships
a different template, so the reminder says so explicitly.
Docs: the `agents-md-instructions-section-naming` requirement now defines
the pragma, and the `liyi migrate` behavior describes refreshing the
`AGENTS.md` region.
The pragma literal is shared by the design-doc appendix, `AGENTS.md`,
`check-template-sync.py`, and `init.rs`, so this commit carries the
mechanical constant/message/docstring updates to keep extraction working.
Behavior changes follow: `liyi init` shipping the pragma, the prefix-based
guard, and the `liyi migrate` Markdown path.
Sidecar churn: the requirement was rehashed and the script's `HEADING`
related edge re-acknowledged; `TEMPLATE_START`, `TEMPLATE_END`, and
`agents_md_block` were re-opened for review.
Original prompt:
> let's use the legacy style but let's make it `START Liyi agent
> instructions rev. 1` and `END liyi agent instructions`, that feels
> better doesn't it?
> Actually this block updates much less frequently than DocToc's case --
> only a Liyi release could possibly bump that, and not for every Liyi
> release, while a DocToc is to be refreshed after every document outline
> change by their user. Let's reword the reminder and start with doc
> changes then implementation.
AI-assisted-by: DeepSeek V4.1 Flash (OpenCode)
Signed-off-by: WANG Xuerui <[email protected]>
Swap the verbose two-clause reminder for the 78-column form, so the
pragma stays readable without wrapping. Used `FROM` rather than a second
`WITH` ("REFRESH WITH `liyi migrate` FROM A NEWER LIYI"), and reworded the
`agents-md-instructions-section-naming` requirement's reference to match
(`BLOCK`, not `SECTION`).
Sidecar churn in the same commit: `TEMPLATE_START` rehashed and the
script's `HEADING` related edge re-acknowledged.
Original prompt:
> Let's agree on a shorter wording, ideally below 80 columns, I'd suggest:
>
> ```markdown
> <!-- DON'T EDIT THIS BLOCK. REFRESH WITH `liyi migrate` WITH A NEWER LIYI. -->
> ```
>
> This is 78 characters. Is this better?
AI-assisted-by: DeepSeek V4.1 Flash (OpenCode)
Signed-off-by: WANG Xuerui <[email protected]>
…init
The portable agent instruction block is now wrapped in a DocToc-style,
version-tracked pragma instead of internal markers that `liyi init`
stripped:
<!-- START liyi agent instructions rev. N -->
<!-- DON'T EDIT THIS BLOCK. REFRESH WITH `liyi migrate` FROM A NEWER LIYI. -->
...
<!-- END liyi agent instructions -->
- `TEMPLATE_REVISION` is the single source for the current revision;
`agents_md_block()` re-renders the block from the repo's AGENTS.md at
that revision, pragma, reminder, and end marker included.
- `find_agents_md_block()` locates a block in arbitrary text without
inspecting the revision, so a block written by an older `liyi` is found.
- `migrate_agents_md()` rewrites a file's block to `TEMPLATE_REVISION`,
preserving surrounding content and skipping the write when already
current (idempotent).
- `init_agents_md()` now keys off the pragma prefix rather than the
`## 立意` heading — which also fixes the duplicate-append bug where a
reworded heading made the guard miss an existing block. `--force`
replaces the existing block instead of appending a second one.
Sidecar churn: init.rs specs were re-generated for the new constants and
functions; `init_agents_md`'s intent was rewritten and left unreviewed.
Original prompt:
> let's go.
AI-assisted-by: DeepSeek V4.1 Flash (OpenCode)
Signed-off-by: WANG Xuerui <[email protected]>
`liyi migrate` previously walked only `.liyi.jsonc` sidecars. It now also refreshes the versioned agent-instruction block in an `AGENTS.md`: - `resolve_agents_md_targets()` finds files carrying the `START liyi agent instructions` pragma: in directory mode it collects files named `AGENTS.md`, and an explicitly-passed file is accepted wherever it lives so a repository's preferred location can be migrated directly. Targeting `AGENTS.md` by name keeps the design doc's heading-less source block from ever being rewritten. - The CLI dispatches sidecar targets to schema migration and agent files to `migrate_agents_md()`, and succeeds when either kind is found (instead of requiring a sidecar). Covered by new discovery unit tests and CLI tests for a stale block, a directory containing both kinds of target, and init idempotency. Original prompt: > let's go. AI-assisted-by: DeepSeek V4.1 Flash (OpenCode) Signed-off-by: WANG Xuerui <[email protected]>
Signed-off-by: WANG Xuerui <[email protected]>
Signed-off-by: WANG Xuerui <[email protected]>
Close the gaps left by the pragma work. Unit (`init.rs`): - create ships a pragma-wrapped block (pragma, reminder, closing marker, exactly one block), - an existing file without a block gets one appended, prefix preserved, - an existing block is refused without `--force` and replaced in place with `--force` (no duplicate). End-to-end (`liyi-cli/tests/cli.rs`, via the compiled binary): - `init` output now also asserts the reminder and closing marker, - `init --force` replaces a stale `rev. 0` block with `rev. 1` and leaves exactly one block. Original prompt: > Okay add the unit tests and E2E tests, one commit for each feature. AI-assisted-by: DeepSeek V4.1 Flash (OpenCode) Signed-off-by: WANG Xuerui <[email protected]>
Close the remaining gaps for the migrate feature. Unit (`init.rs`, `discovery.rs`): - `migrate_agents_md` preserves the content before and after the block, - a directory walk ignores a pragma-carrying file that is not named `AGENTS.md` (the design doc's heading-less source is never targeted). End-to-end (`liyi-cli/tests/cli.rs`, via the compiled binary): - `migrate` is idempotent (a second run leaves the file byte-identical), - a directory containing only an `AGENTS.md` still succeeds, - an explicitly-passed file at a custom location is migrated, - `migrate .` updates `AGENTS.md` but leaves a heading-less `liyi-design.md`-style block untouched. Original prompt: > Okay add the unit tests and E2E tests, one commit for each feature. AI-assisted-by: DeepSeek V4.1 Flash (OpenCode) Signed-off-by: WANG Xuerui <[email protected]>
A directory argument to `liyi migrate` used to walk the whole subtree for `AGENTS.md` files. In a monorepo that cannot tell own-controlled subtrees (`subprojects/*`) from ungoverned ones (`3rdparty/*`, `vendor/*`), so recursive migration could rewrite another project's agent instruction block to our revision. Make discovery strictly mirror `liyi init`: a directory argument contributes exactly its own `AGENTS.md` and never walks. Moving through a tree is now the caller's explicit choice, one governed directory at a time, and a file argument still migrates exactly that file for a preferred location. Both commands now share `AGENTS_MD_FILENAME`, so they cannot disagree about which file they manage. Covered by a unit test (nested `AGENTS.md` is reachable only by naming its directory) and an end-to-end test (`migrate .` leaves `3rdparty/vendored/AGENTS.md` byte-identical). Original prompt: > I actually expect strict equivalence because we're not in a position to > recursively update other projects not under our governance, and right > now we lack the ability to sketch out that boundary in a monorepo. Say > repo root and `subprojects/*` are own-controlled but `3rdparty/*` and > `vendor/*` are NOT. AI-assisted-by: DeepSeek V4.1 Flash (OpenCode) Signed-off-by: WANG Xuerui <[email protected]>
Recursive `liyi migrate` (sidecars) and `liyi check` / `--fix` cannot tell owned subtrees from vendored ones (`3rdparty/`, `vendor/`), so they can rewrite another project's sidecars or agent instructions. Agent-file migration is already non-recursive (3f451fcc38f7), but sidecars and `check` are not, and `.liyiignore` expresses the boundary as an *exclude* list where an *include* concept is wanted. Capture this as a backlog document with the current state, open design questions (include list vs. root markers vs. workspace manifest; which operations to scope; nested VCS boundaries), and a minimum viable direction. No requirement is declared yet. Original prompt: > please document this gap somewhere, as a backlog for now... the > `next-steps.md` might not be a good location specifically, you may want > a new file. AI-assisted-by: DeepSeek V4.1 Flash (OpenCode) Signed-off-by: WANG Xuerui <[email protected]>
Signed-off-by: WANG Xuerui <[email protected]>
立意 writes its agent instructions to `AGENTS.md`, and any harness that reads `AGENTS.md` works out of the box. Make that an explicit, advertised commitment by adding a "Harness compatibility" section to both READMEs. Rather than special-casing vendor instruction files (e.g. Claude Code's `CLAUDE.md`), the README now follows the AGENTS.md convention itself: a harness that does not read `AGENTS.md` is the adopter's responsibility to bridge by placing the block where that harness will read it. This keeps one neutral instruction file instead of a per-harness matrix, and it matches the convention's own backward-compatibility guidance. Original prompt: > Can we sidestep this and call out the discrepancy loud by announcing > somewhere that we explicitly adhere to the https://agents.md > convention? > let's avoid singling out Claude Code and simply claim "If your harness > doesn't read AGENTS.md, it is your responsibility to find another > suitable place for the instruction block and make sure it is being > read by your harness", likewise for the `liyi init` prompt. The latter > can be terse because it's CLI output and the reader might be an LLM > (recent Claude models can be expected to know that and adapt for the > user). No need to mention "liyi commands stay single-file". > "harness" and "harness engineering" tend to be translated as > "驾驭框架/驾驭工程" in zh_CN, not "智能体工具" (that's just "agentic > tools"). fix that and we're good to commit. AI-assisted-by: DeepSeek V4.1 Flash (OpenCode) Signed-off-by: WANG Xuerui <[email protected]>
`liyi init` now prints a one-line note after scaffolding `AGENTS.md`, stating that the block follows the AGENTS.md convention and that a harness which does not read `AGENTS.md` is responsible for placing the block where it will be read. The note is unconditional -- no detection, no vendor filename in the code -- so an agent-driven adoption gets the rule at the moment it matters. Editing inside `main()` shifted its span and changed its hash, so the main.rs sidecar is re-anchored and `main` is left `"reviewed": false` for human re-confirmation. Original prompt: > let's avoid singling out Claude Code and simply claim "If your harness > doesn't read AGENTS.md, it is your responsibility to find another > suitable place for the instruction block and make sure it is being > read by your harness", likewise for the `liyi init` prompt. The latter > can be terse because it's CLI output and the reader might be an LLM > (recent Claude models can be expected to know that and adapt for the > user). No need to mention "liyi commands stay single-file". AI-assisted-by: DeepSeek V4.1 Flash (OpenCode) Signed-off-by: WANG Xuerui <[email protected]>
Signed-off-by: WANG Xuerui <[email protected]>
Signed-off-by: WANG Xuerui <[email protected]>
Remove the completed Tier 1 section and the finished 2A (approval follow-through), 2B (LSP library refactor), and 2F (note context) sections so the backlog lists only outstanding work. Drop the now-dangling reference to item 1.3. Original prompt: > Let's remove the already-done parts from it, refresh the stale info and > drop the explicit mention of number of untracked requirements, and > finally update the banner, in 3 commits. AI-assisted-by: DeepSeek V4.1 Flash (OpenCode) Signed-off-by: WANG Xuerui <[email protected]>
Update the roadmap's cross-references after the shipped Tier 2 work: add the newer design docs to the synthesis list, drop the explicit count of unreferenced requirements, note that the LSP library refactor unblocks Tier 3, and reflect 2D/2E in the sequencing. Original prompt: > Let's remove the already-done parts from it, refresh the stale info and > drop the explicit mention of number of untracked requirements, and > finally update the banner, in 3 commits. AI-assisted-by: DeepSeek V4.1 Flash (OpenCode) Signed-off-by: WANG Xuerui <[email protected]>
Move the "as of" date forward and list the capabilities shipped since the previous baseline. Original prompt: > Let's remove the already-done parts from it, refresh the stale info and > drop the explicit mention of number of untracked requirements, and > finally update the banner, in 3 commits. AI-assisted-by: DeepSeek V4.1 Flash (OpenCode) Signed-off-by: WANG Xuerui <[email protected]>
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.
No description provided.