Add repo-memory CLI test docs
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
# Repo Memory Markdown Test Plan
|
||||
|
||||
## Purpose
|
||||
|
||||
This directory contains the human-readable Markdown test plan for the
|
||||
`repo-memory` CLI.
|
||||
|
||||
It complements package-level Go tests. The goal is to preserve the user-visible
|
||||
command contract in a form that can be reviewed, extended, and replayed without
|
||||
re-deriving behavior from implementation code.
|
||||
|
||||
## Directory Rules
|
||||
|
||||
- one folder per `repo-memory` command or shared area
|
||||
- each folder keeps a `README.md` entrypoint
|
||||
- command folders use `README.md` as an index only
|
||||
- each command test case lives in its own Markdown file named after the case slug
|
||||
- no numeric test IDs
|
||||
- each command case is identified by its concrete file path
|
||||
|
||||
Case file naming pattern:
|
||||
|
||||
```text
|
||||
<case-slug>.md
|
||||
```
|
||||
|
||||
## Authoring Principles
|
||||
|
||||
- focus on externally visible CLI behavior rather than store internals
|
||||
- prefer stable command sequences that a new agent can replay against a temp repo and SQLite DB
|
||||
- document both success contracts and failure boundaries
|
||||
- reuse scenarios from existing Go tests before inventing new cases
|
||||
- keep terminology consistent with the CLI: repo, entry, alias, dependency, event, verify, stale, and needs_review
|
||||
|
||||
## Common Execution Model
|
||||
|
||||
Most cases in this directory assume the same baseline:
|
||||
|
||||
1. create an isolated temporary directory
|
||||
2. create a Git repository fixture such as `TMPDIR/repo`
|
||||
3. choose a database path such as `TMPDIR/repo-memory.db`
|
||||
4. run `repo-memory init --db TMPDIR/repo-memory.db`
|
||||
5. run the target command sequence against that database and repository
|
||||
|
||||
Unless a case says otherwise:
|
||||
|
||||
- assertions should check both exit code and human-readable stdout or stderr
|
||||
- repo-scoped cases should use an actual Git repo so `verified_on_commit` and repo registration are meaningful
|
||||
- `add` and `ingest` may bootstrap schema automatically, but most read commands assume `init` already ran
|
||||
|
||||
## Folder Map
|
||||
|
||||
- `README.md`: global conventions and glossary
|
||||
- `ROADMAP.md`: document progress, planned case backlog, and authored-case register
|
||||
- `_shared/README.md`: reusable fixtures, output assertions, exit-code rules, and repo conventions
|
||||
- `workflows/README.md`: cross-command end-to-end scenarios
|
||||
- per-command folders: command-specific index `README.md` files plus one case document per test case
|
||||
|
||||
## Glossary
|
||||
|
||||
- `repo`: one tracked repository root stored in the memory database
|
||||
- `entry`: one durable knowledge record keyed by repo, kind, key, and optional scope
|
||||
- `alias`: an alternate search term attached to one entry
|
||||
- `dependency`: a file, dir, or glob evidence locator used during verification
|
||||
- `event`: a historical record such as `created`, `updated`, `downgraded`, or `marked_stale`
|
||||
- `needs_review`: knowledge that may still be useful but should be re-checked
|
||||
- `stale`: knowledge that no longer has valid hard evidence and should not be treated as current
|
||||
|
||||
## Relationship To Automated Tests
|
||||
|
||||
The current executable references are:
|
||||
|
||||
- [store_test.go](../../../packages/repo-memory-runtime/internal/store/store_test.go) for import, search, alias, dependency, link, and verification-state transitions
|
||||
- [load_test.go](../../../packages/repo-memory-runtime/internal/documents/load_test.go) for markdown parsing
|
||||
- [main_test.go](../../../packages/repo-memory-runtime/cmd/repo-memory/main_test.go) for verify downgrade heuristics
|
||||
|
||||
These tests do not replace the Markdown plan. They only reduce discovery work.
|
||||
|
||||
When this Markdown plan expands:
|
||||
|
||||
- prefer matching an existing automated scenario first
|
||||
- record any additional manual-only CLI contract coverage explicitly in the relevant command case file
|
||||
- keep [ROADMAP.md](./ROADMAP.md) synchronized with authored files and case slugs
|
||||
@@ -0,0 +1,300 @@
|
||||
# Repo Memory Test Documentation Roadmap
|
||||
|
||||
## Purpose
|
||||
|
||||
This roadmap tracks the human-readable Markdown test plan for `repo-memory`.
|
||||
|
||||
It exists so a new agent can immediately answer four questions without
|
||||
re-reading the whole codebase:
|
||||
|
||||
- which test-plan documents already exist
|
||||
- which cases have already been written down
|
||||
- which cases are still missing
|
||||
- what file should be updated next
|
||||
|
||||
This roadmap is for the Markdown test-plan set under `docs/tests/repo-memory/`.
|
||||
It is not a replacement for automated Go tests.
|
||||
|
||||
## Current Snapshot
|
||||
|
||||
Snapshot date:
|
||||
|
||||
- `2026-03-20`
|
||||
|
||||
Current state:
|
||||
|
||||
- `repo-memory` CLI is implemented for `init`, `add`, `ingest`, `search`, `list`, `events`, `link`, `verify`, and `repos`
|
||||
- package-local automated Go tests already cover markdown parsing, import/search behavior, alias and dependency persistence, relation writes, and verification-state transitions, but they do not yet provide a dedicated CLI Markdown contract map
|
||||
- this roadmap now exists under `docs/tests/repo-memory/ROADMAP.md`
|
||||
- all planned global, shared, workflow, command-index, and command-case Markdown documents in the current `repo-memory` test-plan set have been authored
|
||||
- each implemented `repo-memory` command folder now uses `README.md` as an index plus one Markdown file per planned case
|
||||
- `docs/tests/repo-memory-skill/` can now stay focused on skill-forward behavior while `docs/tests/repo-memory/` owns direct CLI contract coverage
|
||||
- a follow-up edge audit on `2026-03-20` identified seven additional boundary cases, and those cases are now authored in the Markdown plan
|
||||
|
||||
Progress summary for planned test-plan documents, excluding `ROADMAP.md`:
|
||||
|
||||
- planned document files: `39`
|
||||
- authored document files: `39`
|
||||
- planned case slugs in this roadmap: `31`
|
||||
- authored case slugs in this roadmap: `31`
|
||||
|
||||
## Scope
|
||||
|
||||
In scope:
|
||||
|
||||
- `repo-memory init`
|
||||
- `repo-memory add`
|
||||
- `repo-memory ingest`
|
||||
- `repo-memory search`
|
||||
- `repo-memory list`
|
||||
- `repo-memory events`
|
||||
- `repo-memory link`
|
||||
- `repo-memory verify`
|
||||
- `repo-memory repos`
|
||||
- cross-command workflows
|
||||
- shared test conventions for text output, exit codes, temp repos, repo fixtures, and read-only DB inspection where the CLI has no inspection surface
|
||||
|
||||
Out of scope:
|
||||
|
||||
- `skills/repo-memory/` forward execution behavior except as a related reference
|
||||
- implementation details that are not visible through the `repo-memory` CLI contract
|
||||
- future commands that are not currently implemented
|
||||
|
||||
## Tracking Rules
|
||||
|
||||
Directory model:
|
||||
|
||||
- one folder per command or shared area
|
||||
- each folder keeps a `README.md` entrypoint
|
||||
- command folders use `README.md` as an index only
|
||||
- each command case lives in its own Markdown file named after the case slug
|
||||
- cross-command workflow cases remain grouped in `docs/tests/repo-memory/workflows/README.md`
|
||||
|
||||
Case identity:
|
||||
|
||||
- do not use numeric IDs
|
||||
- identify each command case by its concrete file path
|
||||
- identify each workflow case by `path + case slug`
|
||||
- command case file naming pattern:
|
||||
|
||||
```text
|
||||
<case-slug>.md
|
||||
```
|
||||
|
||||
- workflow case heading pattern:
|
||||
|
||||
```md
|
||||
## case: add-search-events-roundtrip
|
||||
```
|
||||
|
||||
Per-case structure inside the case document:
|
||||
|
||||
- `用例意义`
|
||||
- `前置条件`
|
||||
- `输入`
|
||||
- `预期输出`
|
||||
- `断言结论`
|
||||
|
||||
How to update this roadmap when a new case is written:
|
||||
|
||||
1. if it is a command case, create or update the target `<case-slug>.md` file under the relevant command folder
|
||||
2. if it is a command case, add or update the entry in that folder `README.md` index
|
||||
3. if it is a workflow case, add or update the case inside `docs/tests/repo-memory/workflows/README.md`
|
||||
4. move the case slug from `Pending Case Backlog` to `Authored Case Register`
|
||||
5. update the authored counts in `Current Snapshot`
|
||||
6. if a new Markdown file is created, update `Document Progress`
|
||||
|
||||
Allowed status values in this roadmap:
|
||||
|
||||
- `pending`
|
||||
- `in_progress`
|
||||
- `done`
|
||||
- `deferred`
|
||||
|
||||
## Existing Automated Coverage Reference
|
||||
|
||||
The Markdown test-plan set starts from explicit CLI contract docs, but these
|
||||
automated tests already exist and should be used as source material when
|
||||
writing the docs:
|
||||
|
||||
- [store_test.go](../../../packages/repo-memory-runtime/internal/store/store_test.go#L11) `TestImportDocumentAndSearch`
|
||||
- [store_test.go](../../../packages/repo-memory-runtime/internal/store/store_test.go#L67) `TestUpsertEntryWithAliasesAndDependencies`
|
||||
- [store_test.go](../../../packages/repo-memory-runtime/internal/store/store_test.go#L178) `TestApplyVerificationResult`
|
||||
- [load_test.go](../../../packages/repo-memory-runtime/internal/documents/load_test.go#L10) `TestParseFile`
|
||||
- [main_test.go](../../../packages/repo-memory-runtime/cmd/repo-memory/main_test.go#L12) `TestVerifyCandidateDetectsFileChange`
|
||||
- [main_test.go](../../../packages/repo-memory-runtime/cmd/repo-memory/main_test.go#L50) `TestVerifyCandidateMarksMissingDependencyStale`
|
||||
|
||||
These tests do not remove the need for the Markdown plan. They only reduce
|
||||
discovery work.
|
||||
|
||||
## Planned Directory Tree
|
||||
|
||||
```text
|
||||
docs/tests/repo-memory/
|
||||
ROADMAP.md
|
||||
README.md
|
||||
_shared/
|
||||
README.md
|
||||
workflows/
|
||||
README.md
|
||||
init/
|
||||
README.md
|
||||
<case-slug>.md
|
||||
add/
|
||||
README.md
|
||||
<case-slug>.md
|
||||
ingest/
|
||||
README.md
|
||||
<case-slug>.md
|
||||
search/
|
||||
README.md
|
||||
<case-slug>.md
|
||||
list/
|
||||
README.md
|
||||
<case-slug>.md
|
||||
events/
|
||||
README.md
|
||||
<case-slug>.md
|
||||
link/
|
||||
README.md
|
||||
<case-slug>.md
|
||||
verify/
|
||||
README.md
|
||||
<case-slug>.md
|
||||
repos/
|
||||
README.md
|
||||
<case-slug>.md
|
||||
```
|
||||
|
||||
## Document Progress
|
||||
|
||||
| Path | Purpose | Planned Cases | Authored Cases | Status |
|
||||
| --- | --- | ---: | ---: | --- |
|
||||
| `docs/tests/repo-memory/README.md` | Global testing conventions and glossary | 0 | 0 | done |
|
||||
| `docs/tests/repo-memory/_shared/README.md` | Shared fixtures, output assertions, exit codes, and repo rules | 0 | 0 | done |
|
||||
| `docs/tests/repo-memory/workflows/README.md` | Cross-command scenarios | 4 | 4 | done |
|
||||
| `docs/tests/repo-memory/init/README.md` | `init` command case index | 0 | 0 | done |
|
||||
| `docs/tests/repo-memory/init/init-creates-schema-on-empty-db.md` | `init` command case | 1 | 1 | done |
|
||||
| `docs/tests/repo-memory/init/init-is-idempotent-on-existing-db.md` | `init` command case | 1 | 1 | done |
|
||||
| `docs/tests/repo-memory/add/README.md` | `add` command case index | 0 | 0 | done |
|
||||
| `docs/tests/repo-memory/add/add-registers-repo-and-entry.md` | `add` command case | 1 | 1 | done |
|
||||
| `docs/tests/repo-memory/add/add-updates-existing-entry-on-same-kind-and-key.md` | `add` command case | 1 | 1 | done |
|
||||
| `docs/tests/repo-memory/add/add-failed-validation-still-registers-repo.md` | `add` command case | 1 | 1 | done |
|
||||
| `docs/tests/repo-memory/ingest/README.md` | `ingest` command case index | 0 | 0 | done |
|
||||
| `docs/tests/repo-memory/ingest/ingest-imports-docs-ai-markdown.md` | `ingest` command case | 1 | 1 | done |
|
||||
| `docs/tests/repo-memory/ingest/ingest-rejects-when-no-markdown-found.md` | `ingest` command case | 1 | 1 | done |
|
||||
| `docs/tests/repo-memory/ingest/ingest-imports-headingless-markdown-as-single-entry.md` | `ingest` command case | 1 | 1 | done |
|
||||
| `docs/tests/repo-memory/search/README.md` | `search` command case index | 0 | 0 | done |
|
||||
| `docs/tests/repo-memory/search/search-returns-matching-entry-snippet.md` | `search` command case | 1 | 1 | done |
|
||||
| `docs/tests/repo-memory/search/search-matches-alias-with-repo-filter.md` | `search` command case | 1 | 1 | done |
|
||||
| `docs/tests/repo-memory/search/search-returns-no-results-when-empty.md` | `search` command case | 1 | 1 | done |
|
||||
| `docs/tests/repo-memory/search/search-rejects-missing-query.md` | `search` command case | 1 | 1 | done |
|
||||
| `docs/tests/repo-memory/list/README.md` | `list` command case index | 0 | 0 | done |
|
||||
| `docs/tests/repo-memory/list/list-filters-by-kind-and-status.md` | `list` command case | 1 | 1 | done |
|
||||
| `docs/tests/repo-memory/list/list-returns-no-entries-when-empty.md` | `list` command case | 1 | 1 | done |
|
||||
| `docs/tests/repo-memory/events/README.md` | `events` command case index | 0 | 0 | done |
|
||||
| `docs/tests/repo-memory/events/events-reads-history-by-id.md` | `events` command case | 1 | 1 | done |
|
||||
| `docs/tests/repo-memory/events/events-resolves-entry-by-repo-kind-key.md` | `events` command case | 1 | 1 | done |
|
||||
| `docs/tests/repo-memory/events/events-rejects-missing-entry-selector.md` | `events` command case | 1 | 1 | done |
|
||||
| `docs/tests/repo-memory/link/README.md` | `link` command case index | 0 | 0 | done |
|
||||
| `docs/tests/repo-memory/link/link-creates-relation-between-entries.md` | `link` command case | 1 | 1 | done |
|
||||
| `docs/tests/repo-memory/link/link-rejects-missing-relation.md` | `link` command case | 1 | 1 | done |
|
||||
| `docs/tests/repo-memory/link/link-rejects-when-entry-id-missing.md` | `link` command case | 1 | 1 | done |
|
||||
| `docs/tests/repo-memory/verify/README.md` | `verify` command case index | 0 | 0 | done |
|
||||
| `docs/tests/repo-memory/verify/verify-downgrades-changed-file-dependency.md` | `verify` command case | 1 | 1 | done |
|
||||
| `docs/tests/repo-memory/verify/verify-marks-missing-hard-dependency-stale.md` | `verify` command case | 1 | 1 | done |
|
||||
| `docs/tests/repo-memory/verify/verify-prints-no-repos-when-empty.md` | `verify` command case | 1 | 1 | done |
|
||||
| `docs/tests/repo-memory/verify/verify-skips-explicit-repo-without-git-head.md` | `verify` command case | 1 | 1 | done |
|
||||
| `docs/tests/repo-memory/verify/verify-downgrades-entry-missing-verified-on-commit.md` | `verify` command case | 1 | 1 | done |
|
||||
| `docs/tests/repo-memory/repos/README.md` | `repos` command case index | 0 | 0 | done |
|
||||
| `docs/tests/repo-memory/repos/repos-lists-tracked-repositories.md` | `repos` command case | 1 | 1 | done |
|
||||
| `docs/tests/repo-memory/repos/repos-prints-no-repos-when-empty.md` | `repos` command case | 1 | 1 | done |
|
||||
|
||||
## Authoring Order
|
||||
|
||||
Recommended order:
|
||||
|
||||
1. `docs/tests/repo-memory/README.md`
|
||||
2. `docs/tests/repo-memory/_shared/README.md`
|
||||
3. `docs/tests/repo-memory/workflows/README.md`
|
||||
4. `docs/tests/repo-memory/add/README.md` plus its linked case files
|
||||
5. `docs/tests/repo-memory/ingest/README.md` plus its linked case files
|
||||
6. `docs/tests/repo-memory/search/README.md` plus its linked case files
|
||||
7. `docs/tests/repo-memory/verify/README.md` plus its linked case files
|
||||
8. the remaining command indexes and case files
|
||||
|
||||
Reason:
|
||||
|
||||
- the workflow file captures the highest-value repo-memory lifecycle behavior first
|
||||
- command documents can then reuse shared conventions and already-fixed terminology
|
||||
|
||||
## Edge Audit Notes
|
||||
|
||||
Per-command review status after auditing the current CLI source and authored docs:
|
||||
|
||||
- `init`: current coverage is sufficient for now; no additional high-value boundary was found beyond ordinary filesystem failure paths
|
||||
- `add`: now covers both normal upsert flow and the surprising zero-entry repo side effect on failed validation
|
||||
- `ingest`: now covers both ordinary section import and the headingless fallback-entry parser path
|
||||
- `search`: now covers both positive lookup behavior and the required `--query` failure contract
|
||||
- `list`: current coverage is acceptable for now; remaining gaps are mostly lower-priority default-limit behavior and shared uninitialized-schema behavior
|
||||
- `events`: now covers both selector styles and the missing-selector failure contract
|
||||
- `link`: now covers both successful relation writes and missing-input rejection for ids and relation
|
||||
- `verify`: now covers changed-file downgrade, missing-hard-dependency stale, empty-repo set, explicit skip without Git HEAD, and missing `verified_on_commit`
|
||||
- `repos`: current coverage is acceptable for now; the zero-entry repo side effect is intentionally documented from the `add` boundary case
|
||||
|
||||
## Authored Case Register
|
||||
|
||||
| Path | Case Slug | Coverage Note | Status |
|
||||
| --- | --- | --- | --- |
|
||||
| `docs/tests/repo-memory/workflows/README.md` | `add-search-events-roundtrip` | end-to-end write, search, and history roundtrip for one durable entry | done |
|
||||
| `docs/tests/repo-memory/workflows/README.md` | `ingest-search-list-across-sections` | markdown ingest surfaces multiple imported entries through search and list | done |
|
||||
| `docs/tests/repo-memory/workflows/README.md` | `add-link-and-resolve-related-entry` | two entries are linked and the relation is persisted | done |
|
||||
| `docs/tests/repo-memory/workflows/README.md` | `verify-downgrades-after-repo-change` | repo changes propagate into downgraded or stale durable knowledge | done |
|
||||
| `docs/tests/repo-memory/init/init-creates-schema-on-empty-db.md` | `init-creates-schema-on-empty-db` | initializes an empty database path and prints the initialized path | done |
|
||||
| `docs/tests/repo-memory/init/init-is-idempotent-on-existing-db.md` | `init-is-idempotent-on-existing-db` | repeated init succeeds on the same database path | done |
|
||||
| `docs/tests/repo-memory/add/add-registers-repo-and-entry.md` | `add-registers-repo-and-entry` | auto-bootstraps schema, registers the repo, and creates one durable entry | done |
|
||||
| `docs/tests/repo-memory/add/add-updates-existing-entry-on-same-kind-and-key.md` | `add-updates-existing-entry-on-same-kind-and-key` | repeated upsert reuses the same entry id and records an update event | done |
|
||||
| `docs/tests/repo-memory/add/add-failed-validation-still-registers-repo.md` | `add-failed-validation-still-registers-repo` | failed validation still leaves a zero-entry repo row visible through `repos` | done |
|
||||
| `docs/tests/repo-memory/ingest/ingest-imports-docs-ai-markdown.md` | `ingest-imports-docs-ai-markdown` | imports markdown sections under `docs/ai` as confirmed knowledge entries | done |
|
||||
| `docs/tests/repo-memory/ingest/ingest-rejects-when-no-markdown-found.md` | `ingest-rejects-when-no-markdown-found` | rejects an empty scan tree with a stable error message | done |
|
||||
| `docs/tests/repo-memory/ingest/ingest-imports-headingless-markdown-as-single-entry.md` | `ingest-imports-headingless-markdown-as-single-entry` | headingless markdown falls back to one imported entry instead of being skipped | done |
|
||||
| `docs/tests/repo-memory/search/search-returns-matching-entry-snippet.md` | `search-returns-matching-entry-snippet` | returns a ranked text result with status and snippet lines | done |
|
||||
| `docs/tests/repo-memory/search/search-matches-alias-with-repo-filter.md` | `search-matches-alias-with-repo-filter` | matches alias terms while narrowing by repo substring | done |
|
||||
| `docs/tests/repo-memory/search/search-returns-no-results-when-empty.md` | `search-returns-no-results-when-empty` | prints `no results` for an empty search result set | done |
|
||||
| `docs/tests/repo-memory/search/search-rejects-missing-query.md` | `search-rejects-missing-query` | rejects empty search invocation without `--query` | done |
|
||||
| `docs/tests/repo-memory/list/list-filters-by-kind-and-status.md` | `list-filters-by-kind-and-status` | narrows entries by repo substring, kind, and status | done |
|
||||
| `docs/tests/repo-memory/list/list-returns-no-entries-when-empty.md` | `list-returns-no-entries-when-empty` | prints `no entries` when the filtered result set is empty | done |
|
||||
| `docs/tests/repo-memory/events/events-reads-history-by-id.md` | `events-reads-history-by-id` | prints newest-first history for one entry id | done |
|
||||
| `docs/tests/repo-memory/events/events-resolves-entry-by-repo-kind-key.md` | `events-resolves-entry-by-repo-kind-key` | resolves an entry without `--id` when repo, kind, and key are provided | done |
|
||||
| `docs/tests/repo-memory/events/events-rejects-missing-entry-selector.md` | `events-rejects-missing-entry-selector` | rejects calls that omit both `--id` and `--repo+--kind+--key` | done |
|
||||
| `docs/tests/repo-memory/link/link-creates-relation-between-entries.md` | `link-creates-relation-between-entries` | persists one directed relation between two existing entries | done |
|
||||
| `docs/tests/repo-memory/link/link-rejects-missing-relation.md` | `link-rejects-missing-relation` | rejects empty relation input before write | done |
|
||||
| `docs/tests/repo-memory/link/link-rejects-when-entry-id-missing.md` | `link-rejects-when-entry-id-missing` | rejects link requests without both entry ids | done |
|
||||
| `docs/tests/repo-memory/verify/verify-downgrades-changed-file-dependency.md` | `verify-downgrades-changed-file-dependency` | downgrades a confirmed entry to `needs_review` when a tracked file changed | done |
|
||||
| `docs/tests/repo-memory/verify/verify-marks-missing-hard-dependency-stale.md` | `verify-marks-missing-hard-dependency-stale` | marks a confirmed entry `stale` when a hard dependency disappears | done |
|
||||
| `docs/tests/repo-memory/verify/verify-prints-no-repos-when-empty.md` | `verify-prints-no-repos-when-empty` | prints `no repos` when the initialized DB has no tracked repositories | done |
|
||||
| `docs/tests/repo-memory/verify/verify-skips-explicit-repo-without-git-head.md` | `verify-skips-explicit-repo-without-git-head` | explicit repo verification reports a skip when the repo is not a Git repo or has no HEAD | done |
|
||||
| `docs/tests/repo-memory/verify/verify-downgrades-entry-missing-verified-on-commit.md` | `verify-downgrades-entry-missing-verified-on-commit` | entries created without `verified_on_commit` downgrade to `needs_review` once the repo becomes verifiable | done |
|
||||
| `docs/tests/repo-memory/repos/repos-lists-tracked-repositories.md` | `repos-lists-tracked-repositories` | lists every tracked repository with entry counts and update timestamps | done |
|
||||
| `docs/tests/repo-memory/repos/repos-prints-no-repos-when-empty.md` | `repos-prints-no-repos-when-empty` | prints `no repos` for an initialized but unused database | done |
|
||||
|
||||
## Pending Case Backlog
|
||||
|
||||
No pending case slugs remain in the current plan.
|
||||
|
||||
When a new CLI contract or workflow needs coverage:
|
||||
|
||||
1. if it is a command case, create a new `<case-slug>.md` file under the relevant command folder and add it to that folder `README.md` index
|
||||
2. if it is a workflow case, add it to `docs/tests/repo-memory/workflows/README.md`
|
||||
3. add the new slug to `Authored Case Register`
|
||||
4. update `Current Snapshot` and `Document Progress`
|
||||
|
||||
## Definition Of Done
|
||||
|
||||
This roadmap is complete only when all of the following are true:
|
||||
|
||||
- every implemented `repo-memory` command has a corresponding document folder
|
||||
- each planned command index and case document exists
|
||||
- each pending case slug has been either authored or explicitly deferred
|
||||
- the authored-case register matches the actual Markdown files on disk
|
||||
- a new agent can pick any pending case and know exactly where it should be written
|
||||
@@ -0,0 +1,137 @@
|
||||
# Repo Memory Shared Test Conventions
|
||||
|
||||
## Purpose
|
||||
|
||||
This document captures shared assumptions used by multiple `repo-memory`
|
||||
test-plan documents so command and workflow files can stay focused on behavior
|
||||
instead of repeating setup boilerplate.
|
||||
|
||||
## Recommended Fixture Shape
|
||||
|
||||
Use an isolated temp workspace per case:
|
||||
|
||||
- database path: `TMPDIR/repo-memory.db`
|
||||
- repository path: `TMPDIR/repo`
|
||||
- optional second repository path: `TMPDIR/repo-b`
|
||||
- default ingest path: `TMPDIR/repo/docs/ai`
|
||||
- optional evidence file: `TMPDIR/repo/path/to/file`
|
||||
|
||||
Recommended bootstrap command:
|
||||
|
||||
```bash
|
||||
repo-memory init --db TMPDIR/repo-memory.db
|
||||
```
|
||||
|
||||
Recommended repo bootstrap for Git-aware cases:
|
||||
|
||||
```bash
|
||||
git -C TMPDIR/repo init
|
||||
git -C TMPDIR/repo config user.email test@example.com
|
||||
git -C TMPDIR/repo config user.name Tester
|
||||
git -C TMPDIR/repo add .
|
||||
git -C TMPDIR/repo commit -m "init"
|
||||
```
|
||||
|
||||
## Flag Model
|
||||
|
||||
`repo-memory` uses one subcommand-specific flag set per command. There is no
|
||||
root `--json` mode and no shared global flag parser.
|
||||
|
||||
Common flags across multiple commands:
|
||||
|
||||
- `--db`: SQLite database path
|
||||
- `--repo`: repository root or repo-path substring filter depending on command
|
||||
- `--limit`: result limit on read commands
|
||||
|
||||
Case files should call out whether `--repo` is:
|
||||
|
||||
- a required absolute repo root for `add` and `ingest`
|
||||
- an optional substring filter for `search` and `list`
|
||||
- an optional absolute repo root selector for `verify`
|
||||
|
||||
## Text Output Contract
|
||||
|
||||
Successful output is plain text written to stdout.
|
||||
|
||||
Shared assertion guidance:
|
||||
|
||||
- assert stable prefixes or phrases, not timestamp values
|
||||
- prefer checking identifiers, kinds, keys, statuses, and count summaries
|
||||
- when output contains absolute repo paths, compare against the concrete fixture path used by the case
|
||||
|
||||
Representative success phrases:
|
||||
|
||||
- `initialized TMPDIR/repo-memory.db`
|
||||
- `upserted entry 1 (term:AITask)`
|
||||
- `ingested 1 docs from ABS_REPO`
|
||||
- `linked #1 -[related_to]-> #2`
|
||||
- `ABS_REPO: verified 1 entries, 1 downgraded, 0 stale`
|
||||
- `no results`
|
||||
- `no entries`
|
||||
- `no repos`
|
||||
|
||||
## Exit Code Contract
|
||||
|
||||
The current CLI contract uses these exit codes:
|
||||
|
||||
| Exit Code | Meaning | Typical Trigger |
|
||||
| --- | --- | --- |
|
||||
| `0` | success | command completed normally, including empty-result text such as `no results` |
|
||||
| `1` | command failure | invalid flags, missing required values, missing repo docs, unresolved entry, or store/runtime error |
|
||||
| `2` | top-level usage failure | missing subcommand or unknown subcommand |
|
||||
|
||||
When a case expects failure, assert both the non-zero exit code and the human-readable stderr message.
|
||||
|
||||
## Schema Bootstrap Rules
|
||||
|
||||
Current command behavior is intentionally uneven and should be documented:
|
||||
|
||||
- `init` creates schema explicitly
|
||||
- `add` and `ingest` call `Init` internally and can succeed on a fresh DB path
|
||||
- `search`, `list`, `events`, `link`, `verify`, and `repos` assume schema already exists
|
||||
|
||||
If a case relies on automatic schema bootstrap in `add` or `ingest`, state that explicitly in `前置条件` and `断言结论`.
|
||||
|
||||
## Repo Fixture Rules
|
||||
|
||||
Cases covering `add`, `ingest`, or `verify` should state:
|
||||
|
||||
- whether the target repo is a real Git repo
|
||||
- whether a HEAD commit already exists
|
||||
- which file path is being used as evidence or dependency
|
||||
|
||||
`verify` behavior depends on Git state:
|
||||
|
||||
- if a repo has a readable HEAD commit, verification updates repo metadata and evaluates dependencies
|
||||
- if a repo is missing Git state or has no HEAD, the command prints `skipped (not a git repo or no HEAD)` for that repo
|
||||
|
||||
## Markdown Ingest Rules
|
||||
|
||||
`ingest` scans markdown recursively under `docs/ai` by default.
|
||||
|
||||
Shared assertions for ingest cases:
|
||||
|
||||
- `.md` files are discovered recursively
|
||||
- file base name influences imported key prefixes
|
||||
- heading text influences imported `kind` classification and key slug
|
||||
- an empty `docs/ai` tree fails with `no markdown files found under ...`
|
||||
|
||||
## Direct DB Inspection
|
||||
|
||||
Most cases should stay at the CLI contract level.
|
||||
|
||||
One exception is `link`: the CLI currently writes the relation but does not have
|
||||
an inspection command for links. Link cases may use a read-only `sqlite3` query
|
||||
to confirm persistence after the CLI call.
|
||||
|
||||
Typical example:
|
||||
|
||||
```bash
|
||||
sqlite3 TMPDIR/repo-memory.db "SELECT relation FROM knowledge_links WHERE from_entry_id = 1 AND to_entry_id = 2;"
|
||||
```
|
||||
|
||||
## Workflow Authoring Rule
|
||||
|
||||
If a case spans multiple commands, place the end-to-end narrative in
|
||||
`workflows/README.md` first, then add narrower command-level cases only when
|
||||
they are easier to reason about in isolation.
|
||||
@@ -0,0 +1,9 @@
|
||||
# Repo Memory `add` Test Plan Index
|
||||
|
||||
## Case Files
|
||||
|
||||
| Case Slug | File | Coverage Note |
|
||||
| --- | --- | --- |
|
||||
| `add-registers-repo-and-entry` | [add-registers-repo-and-entry.md](./add-registers-repo-and-entry.md) | auto-bootstraps schema, registers the repo, and creates one durable entry |
|
||||
| `add-updates-existing-entry-on-same-kind-and-key` | [add-updates-existing-entry-on-same-kind-and-key.md](./add-updates-existing-entry-on-same-kind-and-key.md) | reuses the same entry id and records an update event on repeated upsert |
|
||||
| `add-failed-validation-still-registers-repo` | [add-failed-validation-still-registers-repo.md](./add-failed-validation-still-registers-repo.md) | failed validation still leaves a zero-entry repo row visible through `repos` |
|
||||
@@ -0,0 +1,32 @@
|
||||
# Case: `add-failed-validation-still-registers-repo`
|
||||
|
||||
## 用例意义
|
||||
|
||||
验证 `add` 即使因为 entry 校验失败退出,仍会留下 repo 注册副作用,这个行为需要被明确记录。
|
||||
|
||||
## 前置条件
|
||||
|
||||
- `TMPDIR/repo` 是一个已提交初始 commit 的 Git 仓库
|
||||
- `TMPDIR/repo-memory.db` 尚不存在
|
||||
|
||||
## 输入
|
||||
|
||||
```bash
|
||||
repo-memory add --db TMPDIR/repo-memory.db --repo TMPDIR/repo --summary "missing kind"
|
||||
repo-memory repos --db TMPDIR/repo-memory.db
|
||||
repo-memory list --db TMPDIR/repo-memory.db --repo repo
|
||||
```
|
||||
|
||||
## 预期输出
|
||||
|
||||
- `add` 退出码为 `1`
|
||||
- `add` 的 stderr 包含 `kind is required`
|
||||
- `repos` 退出码为 `0`
|
||||
- `repos` 输出包含 `TMPDIR/repo (0 entries, updated `
|
||||
- `list` 输出 `no entries`
|
||||
|
||||
## 断言结论
|
||||
|
||||
- `add` 会先初始化数据库并注册 repo,再进入 entry 级校验
|
||||
- 失败的 `add` 不会创建 entry,但会留下可见的零条目 repo 记录
|
||||
- 后续测试或调用方如果依赖“失败无副作用”,必须显式考虑这个例外
|
||||
@@ -0,0 +1,31 @@
|
||||
# Case: `add-registers-repo-and-entry`
|
||||
|
||||
## 用例意义
|
||||
|
||||
验证 `add` 可以在新数据库路径上自动初始化 schema、注册 repo,并写入一条可枚举的 durable knowledge entry。
|
||||
|
||||
## 前置条件
|
||||
|
||||
- `TMPDIR/repo` 是一个已提交初始 commit 的 Git 仓库
|
||||
- 证据文件 `TMPDIR/repo/app/app/src/main/java/foo/AITask.java` 已存在
|
||||
- `TMPDIR/repo-memory.db` 尚不存在
|
||||
|
||||
## 输入
|
||||
|
||||
```bash
|
||||
repo-memory add --db TMPDIR/repo-memory.db --repo TMPDIR/repo --kind term --key AITask --summary "Plan 内嵌任务结构,不是独立表" --status confirmed --source-path TMPDIR/repo/app/app/src/main/java/foo/AITask.java --source-line 42 --alias "AI Task" --dep file:TMPDIR/repo/app/app/src/main/java/foo/AITask.java:hard
|
||||
repo-memory list --db TMPDIR/repo-memory.db --repo repo --kind term --status confirmed
|
||||
```
|
||||
|
||||
## 预期输出
|
||||
|
||||
- `add` 退出码为 `0`
|
||||
- `add` 输出 `upserted entry 1 (term:AITask)`
|
||||
- `list` 输出包含 `#1 [repo] term:AITask [confirmed]`
|
||||
- `list` 输出包含摘要 `Plan 内嵌任务结构,不是独立表`
|
||||
|
||||
## 断言结论
|
||||
|
||||
- `add` 会自动完成 schema bootstrap 与 repo 注册,不要求先单独跑 `init`
|
||||
- 新增 entry 立即可被 `list` 读取
|
||||
- 证据路径、别名、依赖等增强字段不会阻止主写入流程
|
||||
@@ -0,0 +1,35 @@
|
||||
# Case: `add-updates-existing-entry-on-same-kind-and-key`
|
||||
|
||||
## 用例意义
|
||||
|
||||
验证同一 repo 下相同 `kind + key + scope` 再次执行 `add` 时会更新既有 entry,而不是生成重复记录。
|
||||
|
||||
## 前置条件
|
||||
|
||||
- `TMPDIR/repo` 是一个已提交初始 commit 的 Git 仓库
|
||||
- 空数据库已完成 `init`
|
||||
- 已执行过一次:
|
||||
|
||||
```bash
|
||||
repo-memory add --db TMPDIR/repo-memory.db --repo TMPDIR/repo --kind term --key AITask --summary "初版摘要" --status draft
|
||||
```
|
||||
|
||||
## 输入
|
||||
|
||||
```bash
|
||||
repo-memory add --db TMPDIR/repo-memory.db --repo TMPDIR/repo --kind term --key AITask --summary "修订后的摘要" --status confirmed --alias "AI Task"
|
||||
repo-memory events --db TMPDIR/repo-memory.db --id 1
|
||||
repo-memory list --db TMPDIR/repo-memory.db --repo repo --kind term
|
||||
```
|
||||
|
||||
## 预期输出
|
||||
|
||||
- 第二次 `add` 仍输出 `upserted entry 1 (term:AITask)`
|
||||
- `events` 中同时包含 `updated (draft -> confirmed)` 与更早的 `created (- -> draft)`
|
||||
- `list` 中该 entry 的摘要为 `修订后的摘要`
|
||||
|
||||
## 断言结论
|
||||
|
||||
- `add` 的核心语义是 upsert,而不是 append-only create
|
||||
- 更新会保留同一 entry id,同时追加历史事件
|
||||
- 最新摘要、状态、别名会覆盖旧值而不是与旧值并存
|
||||
@@ -0,0 +1,9 @@
|
||||
# Repo Memory `events` Test Plan Index
|
||||
|
||||
## Case Files
|
||||
|
||||
| Case Slug | File | Coverage Note |
|
||||
| --- | --- | --- |
|
||||
| `events-reads-history-by-id` | [events-reads-history-by-id.md](./events-reads-history-by-id.md) | prints newest-first history for one entry id |
|
||||
| `events-resolves-entry-by-repo-kind-key` | [events-resolves-entry-by-repo-kind-key.md](./events-resolves-entry-by-repo-kind-key.md) | resolves an entry without `--id` when repo, kind, and key are provided |
|
||||
| `events-rejects-missing-entry-selector` | [events-rejects-missing-entry-selector.md](./events-rejects-missing-entry-selector.md) | rejects calls that provide neither `--id` nor `--repo + --kind + --key` |
|
||||
@@ -0,0 +1,28 @@
|
||||
# Case: `events-reads-history-by-id`
|
||||
|
||||
## 用例意义
|
||||
|
||||
验证 `events --id` 会返回某个 entry 的历史记录,并按新到旧排序。
|
||||
|
||||
## 前置条件
|
||||
|
||||
- 空数据库已完成 `init`
|
||||
- `TMPDIR/repo` 下已经执行过两次同 key 的 `add`,第二次把状态从 `draft` 更新为 `confirmed`
|
||||
|
||||
## 输入
|
||||
|
||||
```bash
|
||||
repo-memory events --db TMPDIR/repo-memory.db --id 1
|
||||
```
|
||||
|
||||
## 预期输出
|
||||
|
||||
- 命令退出码为 `0`
|
||||
- 第一行包含 `term:AITask [confirmed] #1`
|
||||
- 事件列表包含 `updated (draft -> confirmed)`
|
||||
- 较早事件包含 `created (- -> draft)`
|
||||
|
||||
## 断言结论
|
||||
|
||||
- `events` 不只显示当前状态,也保留状态演进轨迹
|
||||
- 输出顺序是最新事件优先,便于人工快速读到最近变化
|
||||
@@ -0,0 +1,25 @@
|
||||
# Case: `events-rejects-missing-entry-selector`
|
||||
|
||||
## 用例意义
|
||||
|
||||
验证 `events` 在既没有 `--id`,也没有完整 `--repo + --kind + --key` 选择器时,会返回稳定错误。
|
||||
|
||||
## 前置条件
|
||||
|
||||
- 空数据库已完成 `init`
|
||||
|
||||
## 输入
|
||||
|
||||
```bash
|
||||
repo-memory events --db TMPDIR/repo-memory.db
|
||||
```
|
||||
|
||||
## 预期输出
|
||||
|
||||
- 命令退出码为 `1`
|
||||
- stderr 包含 `either --id or --repo+--kind+--key is required`
|
||||
|
||||
## 断言结论
|
||||
|
||||
- `events` 必须先能唯一定位 entry,才会进入历史读取路径
|
||||
- 两种定位方式是互补关系,但至少要提供其中一种
|
||||
@@ -0,0 +1,27 @@
|
||||
# Case: `events-resolves-entry-by-repo-kind-key`
|
||||
|
||||
## 用例意义
|
||||
|
||||
验证 `events` 在没有 `--id` 时,仍可通过 `repo + kind + key` 解析目标 entry。
|
||||
|
||||
## 前置条件
|
||||
|
||||
- 空数据库已完成 `init`
|
||||
- `TMPDIR/repo` 下已存在 `term:AITask` 一条 entry
|
||||
|
||||
## 输入
|
||||
|
||||
```bash
|
||||
repo-memory events --db TMPDIR/repo-memory.db --repo TMPDIR/repo --kind term --key AITask
|
||||
```
|
||||
|
||||
## 预期输出
|
||||
|
||||
- 命令退出码为 `0`
|
||||
- 第一行包含 `term:AITask`
|
||||
- 事件列表至少包含一条 `created`
|
||||
|
||||
## 断言结论
|
||||
|
||||
- `events` 支持两种定位方式:`--id` 或 `--repo + --kind + --key`
|
||||
- 对调用方来说,repo-scoped natural key 足以定位单条 durable knowledge
|
||||
@@ -0,0 +1,9 @@
|
||||
# Repo Memory `ingest` Test Plan Index
|
||||
|
||||
## Case Files
|
||||
|
||||
| Case Slug | File | Coverage Note |
|
||||
| --- | --- | --- |
|
||||
| `ingest-imports-docs-ai-markdown` | [ingest-imports-docs-ai-markdown.md](./ingest-imports-docs-ai-markdown.md) | imports markdown sections under `docs/ai` as confirmed knowledge entries |
|
||||
| `ingest-rejects-when-no-markdown-found` | [ingest-rejects-when-no-markdown-found.md](./ingest-rejects-when-no-markdown-found.md) | rejects an empty scan tree with a stable error message |
|
||||
| `ingest-imports-headingless-markdown-as-single-entry` | [ingest-imports-headingless-markdown-as-single-entry.md](./ingest-imports-headingless-markdown-as-single-entry.md) | imports headingless markdown as one fallback `Overview` entry |
|
||||
@@ -0,0 +1,45 @@
|
||||
# Case: `ingest-imports-docs-ai-markdown`
|
||||
|
||||
## 用例意义
|
||||
|
||||
验证 `ingest` 会扫描 `docs/ai` 下的 Markdown,并把 section 导入为可检索的 durable knowledge entry。
|
||||
|
||||
## 前置条件
|
||||
|
||||
- `TMPDIR/repo` 是一个已提交初始 commit 的 Git 仓库
|
||||
- `TMPDIR/repo/docs/ai/repo-memory.md` 内容至少包含:
|
||||
|
||||
```md
|
||||
# Repo Memory
|
||||
|
||||
## Module Map
|
||||
|
||||
- gateway
|
||||
- app/app
|
||||
|
||||
## Danger Zones
|
||||
|
||||
- shared libs first
|
||||
```
|
||||
|
||||
- `TMPDIR/repo-memory.db` 尚不存在
|
||||
|
||||
## 输入
|
||||
|
||||
```bash
|
||||
repo-memory ingest --db TMPDIR/repo-memory.db --repo TMPDIR/repo
|
||||
repo-memory list --db TMPDIR/repo-memory.db --repo repo
|
||||
```
|
||||
|
||||
## 预期输出
|
||||
|
||||
- `ingest` 退出码为 `0`
|
||||
- `ingest` 输出 `ingested 1 docs from ABS_REPO`
|
||||
- `list` 输出包含 `module:repo-memory:module-map [confirmed]`
|
||||
- `list` 输出包含 `danger:repo-memory:danger-zones [confirmed]`
|
||||
|
||||
## 断言结论
|
||||
|
||||
- 一个 Markdown 文件中的多个 section 会被拆成多条知识 entry
|
||||
- `ingest` 会自动初始化数据库并注册 repo
|
||||
- 从 `repo-memory.md` 导入的 `Module Map`、`Danger Zones` 会被分类为不同 kind
|
||||
@@ -0,0 +1,38 @@
|
||||
# Case: `ingest-imports-headingless-markdown-as-single-entry`
|
||||
|
||||
## 用例意义
|
||||
|
||||
验证 `ingest` 遇到没有任何 Markdown heading 的文档时,不会跳过,而是回退为单条导入 entry。
|
||||
|
||||
## 前置条件
|
||||
|
||||
- `TMPDIR/repo` 是一个已提交初始 commit 的 Git 仓库
|
||||
- `TMPDIR/repo/docs/ai/repo-memory.md` 存在,内容只有普通段落,没有任何 `#` heading,例如:
|
||||
|
||||
```md
|
||||
This repository keeps AI memory notes near docs/ai.
|
||||
Gateway owns ingress and app/app owns orchestration.
|
||||
```
|
||||
|
||||
- 空数据库已完成 `init`
|
||||
|
||||
## 输入
|
||||
|
||||
```bash
|
||||
repo-memory ingest --db TMPDIR/repo-memory.db --repo TMPDIR/repo
|
||||
repo-memory list --db TMPDIR/repo-memory.db --repo repo
|
||||
repo-memory search --db TMPDIR/repo-memory.db --repo repo --query "Gateway orchestration"
|
||||
```
|
||||
|
||||
## 预期输出
|
||||
|
||||
- `ingest` 退出码为 `0`
|
||||
- `ingest` 输出 `ingested 1 docs from ABS_REPO`
|
||||
- `list` 输出包含 `decision:repo-memory:overview [confirmed]`
|
||||
- `search` 输出包含 `decision:repo-memory:overview`
|
||||
|
||||
## 断言结论
|
||||
|
||||
- headingless markdown 不会被忽略
|
||||
- 该类文档会以回退 heading `Overview` 导入为单条 entry
|
||||
- 回退导入的 entry 仍然可以被 `list` 与 `search` 正常消费
|
||||
@@ -0,0 +1,27 @@
|
||||
# Case: `ingest-rejects-when-no-markdown-found`
|
||||
|
||||
## 用例意义
|
||||
|
||||
验证 `ingest` 在扫描目录存在但没有 Markdown 文件时,会返回稳定的失败信息而不是静默成功。
|
||||
|
||||
## 前置条件
|
||||
|
||||
- `TMPDIR/repo` 是一个已提交初始 commit 的 Git 仓库
|
||||
- `TMPDIR/repo/docs/ai/` 目录存在但为空
|
||||
- 空数据库已完成 `init`
|
||||
|
||||
## 输入
|
||||
|
||||
```bash
|
||||
repo-memory ingest --db TMPDIR/repo-memory.db --repo TMPDIR/repo
|
||||
```
|
||||
|
||||
## 预期输出
|
||||
|
||||
- 命令退出码为 `1`
|
||||
- stderr 包含 `no markdown files found under ABS_REPO/docs/ai`
|
||||
|
||||
## 断言结论
|
||||
|
||||
- `ingest` 不会把“没有可导入文档”误报为成功
|
||||
- 错误边界发生在导入阶段,repo 路径本身仍然是合法的
|
||||
@@ -0,0 +1,8 @@
|
||||
# Repo Memory `init` Test Plan Index
|
||||
|
||||
## Case Files
|
||||
|
||||
| Case Slug | File | Coverage Note |
|
||||
| --- | --- | --- |
|
||||
| `init-creates-schema-on-empty-db` | [init-creates-schema-on-empty-db.md](./init-creates-schema-on-empty-db.md) | initializes an empty database path and prints the initialized path |
|
||||
| `init-is-idempotent-on-existing-db` | [init-is-idempotent-on-existing-db.md](./init-is-idempotent-on-existing-db.md) | repeated init succeeds on the same database path |
|
||||
@@ -0,0 +1,25 @@
|
||||
# Case: `init-creates-schema-on-empty-db`
|
||||
|
||||
## 用例意义
|
||||
|
||||
验证在空数据库路径上执行 `init` 会创建可用的 repo-memory schema,并返回稳定的初始化文本。
|
||||
|
||||
## 前置条件
|
||||
|
||||
- 选择一个尚不存在的数据库路径 `TMPDIR/repo-memory.db`
|
||||
|
||||
## 输入
|
||||
|
||||
```bash
|
||||
repo-memory init --db TMPDIR/repo-memory.db
|
||||
```
|
||||
|
||||
## 预期输出
|
||||
|
||||
- 命令退出码为 `0`
|
||||
- stdout 等于 `initialized TMPDIR/repo-memory.db`
|
||||
|
||||
## 断言结论
|
||||
|
||||
- `init` 在空路径上可以直接完成 schema 初始化
|
||||
- 初始化结果足以让后续 `search`、`list`、`repos` 等只读命令使用同一数据库
|
||||
@@ -0,0 +1,26 @@
|
||||
# Case: `init-is-idempotent-on-existing-db`
|
||||
|
||||
## 用例意义
|
||||
|
||||
验证 `init` 在已初始化数据库上重复执行仍然成功,不要求调用方先判断 schema 是否存在。
|
||||
|
||||
## 前置条件
|
||||
|
||||
- `TMPDIR/repo-memory.db` 已经执行过一次 `repo-memory init --db TMPDIR/repo-memory.db`
|
||||
|
||||
## 输入
|
||||
|
||||
```bash
|
||||
repo-memory init --db TMPDIR/repo-memory.db
|
||||
repo-memory init --db TMPDIR/repo-memory.db
|
||||
```
|
||||
|
||||
## 预期输出
|
||||
|
||||
- 两次命令退出码都为 `0`
|
||||
- 两次 stdout 都等于 `initialized TMPDIR/repo-memory.db`
|
||||
|
||||
## 断言结论
|
||||
|
||||
- `init` 是幂等操作
|
||||
- 测试夹具或调用脚本可以安全重复执行初始化而不破坏已有数据
|
||||
@@ -0,0 +1,9 @@
|
||||
# Repo Memory `link` Test Plan Index
|
||||
|
||||
## Case Files
|
||||
|
||||
| Case Slug | File | Coverage Note |
|
||||
| --- | --- | --- |
|
||||
| `link-creates-relation-between-entries` | [link-creates-relation-between-entries.md](./link-creates-relation-between-entries.md) | persists one directed relation between two existing entries |
|
||||
| `link-rejects-missing-relation` | [link-rejects-missing-relation.md](./link-rejects-missing-relation.md) | rejects empty relation input before write |
|
||||
| `link-rejects-when-entry-id-missing` | [link-rejects-when-entry-id-missing.md](./link-rejects-when-entry-id-missing.md) | rejects link requests that omit either `--from-id` or `--to-id` |
|
||||
@@ -0,0 +1,28 @@
|
||||
# Case: `link-creates-relation-between-entries`
|
||||
|
||||
## 用例意义
|
||||
|
||||
验证 `link` 可以在两条已存在 entry 之间建立一条可持久化的关系记录。
|
||||
|
||||
## 前置条件
|
||||
|
||||
- 空数据库已完成 `init`
|
||||
- 已存在两条 entry:`#1 term:AITask` 与 `#2 chain:ai-insight.get`
|
||||
|
||||
## 输入
|
||||
|
||||
```bash
|
||||
repo-memory link --db TMPDIR/repo-memory.db --from-id 1 --to-id 2 --relation related_to
|
||||
sqlite3 TMPDIR/repo-memory.db "SELECT relation FROM knowledge_links WHERE from_entry_id = 1 AND to_entry_id = 2;"
|
||||
```
|
||||
|
||||
## 预期输出
|
||||
|
||||
- `link` 命令退出码为 `0`
|
||||
- `link` 输出 `linked #1 -[related_to]-> #2`
|
||||
- SQL 查询返回一行 `related_to`
|
||||
|
||||
## 断言结论
|
||||
|
||||
- `link` 的副作用已落库,而不是只打印成功提示
|
||||
- 关系是定向的,方向由 `from-id` 与 `to-id` 决定
|
||||
@@ -0,0 +1,26 @@
|
||||
# Case: `link-rejects-missing-relation`
|
||||
|
||||
## 用例意义
|
||||
|
||||
验证 `link` 对空 relation 输入给出稳定错误,而不是写入无意义关系。
|
||||
|
||||
## 前置条件
|
||||
|
||||
- 空数据库已完成 `init`
|
||||
- 已存在两条 entry:`#1` 与 `#2`
|
||||
|
||||
## 输入
|
||||
|
||||
```bash
|
||||
repo-memory link --db TMPDIR/repo-memory.db --from-id 1 --to-id 2
|
||||
```
|
||||
|
||||
## 预期输出
|
||||
|
||||
- 命令退出码为 `1`
|
||||
- stderr 包含 `relation is required`
|
||||
|
||||
## 断言结论
|
||||
|
||||
- `relation` 是必填输入
|
||||
- 错误发生在写库前,不会产生半有效的 link 记录
|
||||
@@ -0,0 +1,26 @@
|
||||
# Case: `link-rejects-when-entry-id-missing`
|
||||
|
||||
## 用例意义
|
||||
|
||||
验证 `link` 在缺少 `--from-id` 或 `--to-id` 时,会在写库前拒绝请求。
|
||||
|
||||
## 前置条件
|
||||
|
||||
- 空数据库已完成 `init`
|
||||
- 已存在一条 entry:`#1 term:AITask`
|
||||
|
||||
## 输入
|
||||
|
||||
```bash
|
||||
repo-memory link --db TMPDIR/repo-memory.db --from-id 1 --relation related_to
|
||||
```
|
||||
|
||||
## 预期输出
|
||||
|
||||
- 命令退出码为 `1`
|
||||
- stderr 包含 `both entry ids are required`
|
||||
|
||||
## 断言结论
|
||||
|
||||
- `link` 需要完整的双端 entry id,不能只靠单端 id 建立半关系
|
||||
- 缺失 id 的错误发生在写库前,不会生成不完整 link 记录
|
||||
@@ -0,0 +1,8 @@
|
||||
# Repo Memory `list` Test Plan Index
|
||||
|
||||
## Case Files
|
||||
|
||||
| Case Slug | File | Coverage Note |
|
||||
| --- | --- | --- |
|
||||
| `list-filters-by-kind-and-status` | [list-filters-by-kind-and-status.md](./list-filters-by-kind-and-status.md) | narrows entries by repo substring, kind, and status |
|
||||
| `list-returns-no-entries-when-empty` | [list-returns-no-entries-when-empty.md](./list-returns-no-entries-when-empty.md) | prints `no entries` when the filtered result set is empty |
|
||||
@@ -0,0 +1,34 @@
|
||||
# Case: `list-filters-by-kind-and-status`
|
||||
|
||||
## 用例意义
|
||||
|
||||
验证 `list` 会同时应用 repo、kind、status 过滤条件,而不是只看其中之一。
|
||||
|
||||
## 前置条件
|
||||
|
||||
- 空数据库已完成 `init`
|
||||
- 同一 repo 下已存在三条 entry:
|
||||
|
||||
```bash
|
||||
repo-memory add --db TMPDIR/repo-memory.db --repo TMPDIR/repo --kind term --key AITask --summary "Plan 内嵌任务结构" --status confirmed
|
||||
repo-memory add --db TMPDIR/repo-memory.db --repo TMPDIR/repo --kind term --key AIJob --summary "后台任务封装" --status draft
|
||||
repo-memory add --db TMPDIR/repo-memory.db --repo TMPDIR/repo --kind chain --key ai-insight.get --summary "gateway -> app service -> cache/db" --status confirmed
|
||||
```
|
||||
|
||||
## 输入
|
||||
|
||||
```bash
|
||||
repo-memory list --db TMPDIR/repo-memory.db --repo repo --kind term --status confirmed
|
||||
```
|
||||
|
||||
## 预期输出
|
||||
|
||||
- 命令退出码为 `0`
|
||||
- 输出包含 `term:AITask [confirmed]`
|
||||
- 输出不包含 `AIJob`
|
||||
- 输出不包含 `chain:ai-insight.get`
|
||||
|
||||
## 断言结论
|
||||
|
||||
- `list` 过滤条件是交集语义
|
||||
- repo 路径过滤、kind 过滤、status 过滤可以叠加使用
|
||||
@@ -0,0 +1,25 @@
|
||||
# Case: `list-returns-no-entries-when-empty`
|
||||
|
||||
## 用例意义
|
||||
|
||||
验证 `list` 在没有任何匹配 entry 时返回稳定空结果文本。
|
||||
|
||||
## 前置条件
|
||||
|
||||
- 空数据库已完成 `init`
|
||||
|
||||
## 输入
|
||||
|
||||
```bash
|
||||
repo-memory list --db TMPDIR/repo-memory.db --repo repo --kind term --status confirmed
|
||||
```
|
||||
|
||||
## 预期输出
|
||||
|
||||
- 命令退出码为 `0`
|
||||
- stdout 等于 `no entries`
|
||||
|
||||
## 断言结论
|
||||
|
||||
- 空列表属于正常读取路径,不应被当作错误
|
||||
- 调用方可以通过固定文本判断当前过滤条件下无匹配项
|
||||
@@ -0,0 +1,8 @@
|
||||
# Repo Memory `repos` Test Plan Index
|
||||
|
||||
## Case Files
|
||||
|
||||
| Case Slug | File | Coverage Note |
|
||||
| --- | --- | --- |
|
||||
| `repos-lists-tracked-repositories` | [repos-lists-tracked-repositories.md](./repos-lists-tracked-repositories.md) | lists every tracked repository with entry counts and update timestamps |
|
||||
| `repos-prints-no-repos-when-empty` | [repos-prints-no-repos-when-empty.md](./repos-prints-no-repos-when-empty.md) | prints `no repos` for an initialized but unused database |
|
||||
@@ -0,0 +1,28 @@
|
||||
# Case: `repos-lists-tracked-repositories`
|
||||
|
||||
## 用例意义
|
||||
|
||||
验证 `repos` 会列出当前数据库中所有已注册仓库,并附带 entry 数量。
|
||||
|
||||
## 前置条件
|
||||
|
||||
- 空数据库已完成 `init`
|
||||
- 已存在两个 Git 仓库:`TMPDIR/cupid-service` 与 `TMPDIR/mars-service`
|
||||
- 已分别执行一次 `add`,使两个 repo 都被注册到数据库
|
||||
|
||||
## 输入
|
||||
|
||||
```bash
|
||||
repo-memory repos --db TMPDIR/repo-memory.db
|
||||
```
|
||||
|
||||
## 预期输出
|
||||
|
||||
- 命令退出码为 `0`
|
||||
- 输出包含 `TMPDIR/cupid-service (1 entries, updated `
|
||||
- 输出包含 `TMPDIR/mars-service (1 entries, updated `
|
||||
|
||||
## 断言结论
|
||||
|
||||
- `repos` 以 repo 为聚合维度展示当前内存库覆盖范围
|
||||
- 输出中的条目数来自持久化 entry 统计,而不是瞬时搜索结果
|
||||
@@ -0,0 +1,25 @@
|
||||
# Case: `repos-prints-no-repos-when-empty`
|
||||
|
||||
## 用例意义
|
||||
|
||||
验证 `repos` 在数据库已初始化但没有任何 repo 记录时返回稳定空结果文本。
|
||||
|
||||
## 前置条件
|
||||
|
||||
- 空数据库已完成 `init`
|
||||
|
||||
## 输入
|
||||
|
||||
```bash
|
||||
repo-memory repos --db TMPDIR/repo-memory.db
|
||||
```
|
||||
|
||||
## 预期输出
|
||||
|
||||
- 命令退出码为 `0`
|
||||
- stdout 等于 `no repos`
|
||||
|
||||
## 断言结论
|
||||
|
||||
- `repos` 的空结果是正常状态,而不是错误
|
||||
- 该命令可作为“数据库里是否已经有任何 repo memory” 的快速探针
|
||||
@@ -0,0 +1,10 @@
|
||||
# Repo Memory `search` Test Plan Index
|
||||
|
||||
## Case Files
|
||||
|
||||
| Case Slug | File | Coverage Note |
|
||||
| --- | --- | --- |
|
||||
| `search-returns-matching-entry-snippet` | [search-returns-matching-entry-snippet.md](./search-returns-matching-entry-snippet.md) | returns a ranked text result with status and snippet lines |
|
||||
| `search-matches-alias-with-repo-filter` | [search-matches-alias-with-repo-filter.md](./search-matches-alias-with-repo-filter.md) | matches alias terms while narrowing by repo substring |
|
||||
| `search-returns-no-results-when-empty` | [search-returns-no-results-when-empty.md](./search-returns-no-results-when-empty.md) | prints `no results` for an empty search result set |
|
||||
| `search-rejects-missing-query` | [search-rejects-missing-query.md](./search-rejects-missing-query.md) | rejects invocations that omit the required `--query` flag |
|
||||
@@ -0,0 +1,34 @@
|
||||
# Case: `search-matches-alias-with-repo-filter`
|
||||
|
||||
## 用例意义
|
||||
|
||||
验证 `search` 会命中 alias,同时 `--repo` 作为路径子串过滤器只返回目标仓库的结果。
|
||||
|
||||
## 前置条件
|
||||
|
||||
- 空数据库已完成 `init`
|
||||
- 已存在两个 Git 仓库:`TMPDIR/cupid-service` 与 `TMPDIR/mars-service`
|
||||
- 已分别执行:
|
||||
|
||||
```bash
|
||||
repo-memory add --db TMPDIR/repo-memory.db --repo TMPDIR/cupid-service --kind term --key AITask --summary "Plan 内嵌任务结构" --status confirmed --alias "plan task"
|
||||
repo-memory add --db TMPDIR/repo-memory.db --repo TMPDIR/mars-service --kind term --key DeployPlan --summary "发布计划" --status confirmed --alias "release plan"
|
||||
```
|
||||
|
||||
## 输入
|
||||
|
||||
```bash
|
||||
repo-memory search --db TMPDIR/repo-memory.db --repo cupid --query "plan task"
|
||||
```
|
||||
|
||||
## 预期输出
|
||||
|
||||
- 命令退出码为 `0`
|
||||
- 输出包含 `[cupid-service] term:AITask [confirmed]`
|
||||
- 输出不包含 `[mars-service]`
|
||||
|
||||
## 断言结论
|
||||
|
||||
- alias 会进入搜索面
|
||||
- `--repo` 是 repo path substring filter,而不是必须传完整绝对路径
|
||||
- 过滤发生在结果集层面,不影响 alias 命中能力
|
||||
@@ -0,0 +1,25 @@
|
||||
# Case: `search-rejects-missing-query`
|
||||
|
||||
## 用例意义
|
||||
|
||||
验证 `search` 对缺失 `--query` 的调用给出稳定失败契约。
|
||||
|
||||
## 前置条件
|
||||
|
||||
- 空数据库已完成 `init`
|
||||
|
||||
## 输入
|
||||
|
||||
```bash
|
||||
repo-memory search --db TMPDIR/repo-memory.db
|
||||
```
|
||||
|
||||
## 预期输出
|
||||
|
||||
- 命令退出码为 `1`
|
||||
- stderr 包含 `--query is required`
|
||||
|
||||
## 断言结论
|
||||
|
||||
- `search` 不支持“列出全部”式空查询
|
||||
- 缺失查询词属于输入错误,而不是空结果
|
||||
@@ -0,0 +1,31 @@
|
||||
# Case: `search-returns-matching-entry-snippet`
|
||||
|
||||
## 用例意义
|
||||
|
||||
验证 `search` 返回的文本结果既包含 entry 身份信息,也包含便于人工判断的 snippet。
|
||||
|
||||
## 前置条件
|
||||
|
||||
- 空数据库已完成 `init`
|
||||
- `TMPDIR/repo` 下已有一条 `confirmed` entry:
|
||||
|
||||
```bash
|
||||
repo-memory add --db TMPDIR/repo-memory.db --repo TMPDIR/repo --kind chain --key ai-insight.get --summary "gateway -> app service -> cache/db" --detail "The AI insight read path goes through gateway before app service reaches cache and database." --status confirmed
|
||||
```
|
||||
|
||||
## 输入
|
||||
|
||||
```bash
|
||||
repo-memory search --db TMPDIR/repo-memory.db --repo repo --query "insight gateway"
|
||||
```
|
||||
|
||||
## 预期输出
|
||||
|
||||
- 命令退出码为 `0`
|
||||
- 第一行包含 `1. [repo] chain:ai-insight.get [confirmed]`
|
||||
- 后续文本包含 `gateway` 的 snippet 片段
|
||||
|
||||
## 断言结论
|
||||
|
||||
- `search` 的核心输出不是纯 id 列表,而是可直接消费的人工排查文本
|
||||
- 查询会同时命中 `key`、`summary`、`detail`
|
||||
@@ -0,0 +1,25 @@
|
||||
# Case: `search-returns-no-results-when-empty`
|
||||
|
||||
## 用例意义
|
||||
|
||||
验证 `search` 在没有命中项时返回稳定空结果文本,而不是异常退出。
|
||||
|
||||
## 前置条件
|
||||
|
||||
- 空数据库已完成 `init`
|
||||
|
||||
## 输入
|
||||
|
||||
```bash
|
||||
repo-memory search --db TMPDIR/repo-memory.db --query "missing term"
|
||||
```
|
||||
|
||||
## 预期输出
|
||||
|
||||
- 命令退出码为 `0`
|
||||
- stdout 等于 `no results`
|
||||
|
||||
## 断言结论
|
||||
|
||||
- 空搜索结果被视为正常控制流
|
||||
- 调用方可以用退出码 `0` + 文本 `no results` 区分“没命中”和“命令失败”
|
||||
@@ -0,0 +1,11 @@
|
||||
# Repo Memory `verify` Test Plan Index
|
||||
|
||||
## Case Files
|
||||
|
||||
| Case Slug | File | Coverage Note |
|
||||
| --- | --- | --- |
|
||||
| `verify-downgrades-changed-file-dependency` | [verify-downgrades-changed-file-dependency.md](./verify-downgrades-changed-file-dependency.md) | downgrades a confirmed entry to `needs_review` when a tracked file changed |
|
||||
| `verify-marks-missing-hard-dependency-stale` | [verify-marks-missing-hard-dependency-stale.md](./verify-marks-missing-hard-dependency-stale.md) | marks a confirmed entry `stale` when a hard dependency disappears |
|
||||
| `verify-prints-no-repos-when-empty` | [verify-prints-no-repos-when-empty.md](./verify-prints-no-repos-when-empty.md) | prints `no repos` when the initialized DB has no tracked repositories |
|
||||
| `verify-skips-explicit-repo-without-git-head` | [verify-skips-explicit-repo-without-git-head.md](./verify-skips-explicit-repo-without-git-head.md) | prints a skip line when the explicit repo is not a Git repo or has no HEAD |
|
||||
| `verify-downgrades-entry-missing-verified-on-commit` | [verify-downgrades-entry-missing-verified-on-commit.md](./verify-downgrades-entry-missing-verified-on-commit.md) | downgrades an entry to `needs_review` once the repo becomes verifiable but the entry lacks `verified_on_commit` |
|
||||
@@ -0,0 +1,36 @@
|
||||
# Case: `verify-downgrades-changed-file-dependency`
|
||||
|
||||
## 用例意义
|
||||
|
||||
验证 `verify` 在硬依赖文件内容发生变更时,会把 `confirmed` entry 降级为 `needs_review`。
|
||||
|
||||
## 前置条件
|
||||
|
||||
- 空数据库已完成 `init`
|
||||
- `TMPDIR/repo` 是一个已提交初始 commit 的 Git 仓库
|
||||
- 已执行:
|
||||
|
||||
```bash
|
||||
repo-memory add --db TMPDIR/repo-memory.db --repo TMPDIR/repo --kind term --key AITask --summary "Plan 内嵌任务结构" --status confirmed --dep file:TMPDIR/repo/foo.txt:hard
|
||||
```
|
||||
|
||||
- 在执行 `verify` 前,`TMPDIR/repo/foo.txt` 已被修改但尚未重新验证
|
||||
|
||||
## 输入
|
||||
|
||||
```bash
|
||||
repo-memory verify --db TMPDIR/repo-memory.db --repo TMPDIR/repo
|
||||
repo-memory list --db TMPDIR/repo-memory.db --repo repo --status needs_review
|
||||
repo-memory events --db TMPDIR/repo-memory.db --id 1
|
||||
```
|
||||
|
||||
## 预期输出
|
||||
|
||||
- `verify` 输出包含 `verified 1 entries, 1 downgraded, 0 stale`
|
||||
- `list` 输出包含 `term:AITask [needs_review]`
|
||||
- `events` 输出包含 `downgraded (confirmed -> needs_review)`
|
||||
|
||||
## 断言结论
|
||||
|
||||
- 文件变更不会直接删除知识,而是先降级为 `needs_review`
|
||||
- `verify` 会同时更新当前状态与历史事件
|
||||
@@ -0,0 +1,37 @@
|
||||
# Case: `verify-downgrades-entry-missing-verified-on-commit`
|
||||
|
||||
## 用例意义
|
||||
|
||||
验证 entry 一旦缺少 `verified_on_commit`,在 repo 变得可验证后会被 `verify` 降级到 `needs_review`。
|
||||
|
||||
## 前置条件
|
||||
|
||||
- `TMPDIR/repo` 目录最开始不是 Git repo,但包含证据文件 `foo.txt`
|
||||
- 已执行:
|
||||
|
||||
```bash
|
||||
repo-memory add --db TMPDIR/repo-memory.db --repo TMPDIR/repo --kind term --key AITask --summary "Recorded before git init" --status confirmed --dep file:TMPDIR/repo/foo.txt:hard
|
||||
```
|
||||
|
||||
- 之后才把 `TMPDIR/repo` 初始化为 Git repo,并完成第一次 commit
|
||||
|
||||
## 输入
|
||||
|
||||
```bash
|
||||
repo-memory verify --db TMPDIR/repo-memory.db --repo TMPDIR/repo
|
||||
repo-memory list --db TMPDIR/repo-memory.db --repo repo --status needs_review
|
||||
repo-memory events --db TMPDIR/repo-memory.db --id 1
|
||||
```
|
||||
|
||||
## 预期输出
|
||||
|
||||
- `verify` 退出码为 `0`
|
||||
- `verify` 输出包含 `verified 1 entries, 1 downgraded, 0 stale`
|
||||
- `list` 输出包含 `term:AITask [needs_review]`
|
||||
- `events` 输出包含 `downgraded (confirmed -> needs_review)`
|
||||
- `events` 输出包含原因 `missing verified_on_commit`
|
||||
|
||||
## 断言结论
|
||||
|
||||
- 只要 entry 缺少 `verified_on_commit`,即使依赖文件当前存在,也不能继续保持 `confirmed`
|
||||
- 这个边界主要出现在“先写 repo-memory,后补 Git 历史”的仓库演进阶段
|
||||
@@ -0,0 +1,36 @@
|
||||
# Case: `verify-marks-missing-hard-dependency-stale`
|
||||
|
||||
## 用例意义
|
||||
|
||||
验证 `verify` 在硬依赖文件已经不存在时,会把 entry 标记为 `stale`。
|
||||
|
||||
## 前置条件
|
||||
|
||||
- 空数据库已完成 `init`
|
||||
- `TMPDIR/repo` 是一个已提交初始 commit 的 Git 仓库
|
||||
- 已执行:
|
||||
|
||||
```bash
|
||||
repo-memory add --db TMPDIR/repo-memory.db --repo TMPDIR/repo --kind term --key AITask --summary "Plan 内嵌任务结构" --status confirmed --dep file:TMPDIR/repo/missing.txt:hard
|
||||
```
|
||||
|
||||
- `TMPDIR/repo/missing.txt` 不存在
|
||||
|
||||
## 输入
|
||||
|
||||
```bash
|
||||
repo-memory verify --db TMPDIR/repo-memory.db --repo TMPDIR/repo
|
||||
repo-memory list --db TMPDIR/repo-memory.db --repo repo --status stale
|
||||
repo-memory events --db TMPDIR/repo-memory.db --id 1
|
||||
```
|
||||
|
||||
## 预期输出
|
||||
|
||||
- `verify` 输出包含 `verified 1 entries, 0 downgraded, 1 stale`
|
||||
- `list` 输出包含 `term:AITask [stale]`
|
||||
- `events` 输出包含 `marked_stale (confirmed -> stale)`
|
||||
|
||||
## 断言结论
|
||||
|
||||
- 缺失的硬依赖会让知识条目直接过期,而不是只进入待复核状态
|
||||
- `stale` 与 `needs_review` 是两种不同的 verify 结果
|
||||
@@ -0,0 +1,25 @@
|
||||
# Case: `verify-prints-no-repos-when-empty`
|
||||
|
||||
## 用例意义
|
||||
|
||||
验证 `verify` 在已初始化但尚未注册任何 repo 的数据库上返回稳定空结果文本。
|
||||
|
||||
## 前置条件
|
||||
|
||||
- 空数据库已完成 `init`
|
||||
|
||||
## 输入
|
||||
|
||||
```bash
|
||||
repo-memory verify --db TMPDIR/repo-memory.db
|
||||
```
|
||||
|
||||
## 预期输出
|
||||
|
||||
- 命令退出码为 `0`
|
||||
- stdout 等于 `no repos`
|
||||
|
||||
## 断言结论
|
||||
|
||||
- 没有 tracked repo 时,`verify` 走正常空结果路径
|
||||
- 调用方可以先跑 `verify`,再根据 `no repos` 决定是否需要补充 `add` 或 `ingest`
|
||||
@@ -0,0 +1,28 @@
|
||||
# Case: `verify-skips-explicit-repo-without-git-head`
|
||||
|
||||
## 用例意义
|
||||
|
||||
验证 `verify --repo <path>` 在目标目录不是 Git repo 或没有 HEAD commit 时,会返回稳定 skip 文本,而不是失败。
|
||||
|
||||
## 前置条件
|
||||
|
||||
- `TMPDIR/repo` 目录存在,但不是 Git repo,或者已经 `git init` 但还没有第一次 commit
|
||||
- 空数据库已完成 `init`
|
||||
|
||||
## 输入
|
||||
|
||||
```bash
|
||||
repo-memory verify --db TMPDIR/repo-memory.db --repo TMPDIR/repo
|
||||
repo-memory repos --db TMPDIR/repo-memory.db
|
||||
```
|
||||
|
||||
## 预期输出
|
||||
|
||||
- `verify` 退出码为 `0`
|
||||
- `verify` 输出包含 `TMPDIR/repo: skipped (not a git repo or no HEAD)`
|
||||
- `repos` 输出 `no repos`
|
||||
|
||||
## 断言结论
|
||||
|
||||
- 对显式 repo 的 verify,缺失 Git HEAD 被视为可跳过状态,不是命令失败
|
||||
- skip 发生在 repo 注册之前,因此不会额外写入 repo 记录
|
||||
@@ -0,0 +1,138 @@
|
||||
# Repo Memory Workflow Test Plan
|
||||
|
||||
## Scope
|
||||
|
||||
This document tracks cross-command scenarios where the main value is the
|
||||
interaction between multiple `repo-memory` subcommands.
|
||||
|
||||
All examples assume:
|
||||
|
||||
- isolated temp DB and repo fixtures
|
||||
- assertions follow the shared rules in [../_shared/README.md](../_shared/README.md)
|
||||
- commands use the concrete fixture paths created for the case
|
||||
|
||||
## case: add-search-events-roundtrip
|
||||
|
||||
### 用例意义
|
||||
|
||||
验证 `add -> search -> events` 的主干链路可用,确保新写入的 durable knowledge 能被立即检索并带有可追溯历史。
|
||||
|
||||
### 前置条件
|
||||
|
||||
- `TMPDIR/repo` 是一个已提交初始 commit 的 Git 仓库
|
||||
- 证据文件 `TMPDIR/repo/app/app/src/main/java/foo/AITask.java` 已存在
|
||||
- 空数据库已完成 `init`
|
||||
|
||||
### 输入
|
||||
|
||||
```bash
|
||||
repo-memory add --db TMPDIR/repo-memory.db --repo TMPDIR/repo --kind term --key AITask --summary "Plan 内嵌任务结构,不是独立表" --status confirmed --source-path TMPDIR/repo/app/app/src/main/java/foo/AITask.java --source-line 42 --alias "AI Task" --dep file:TMPDIR/repo/app/app/src/main/java/foo/AITask.java:hard
|
||||
repo-memory search --db TMPDIR/repo-memory.db --repo repo --query "AI Task"
|
||||
repo-memory events --db TMPDIR/repo-memory.db --id 1
|
||||
```
|
||||
|
||||
### 预期输出
|
||||
|
||||
- `add` 输出 `upserted entry 1 (term:AITask)`
|
||||
- `search` 返回 `term:AITask [confirmed]`
|
||||
- `events` 以 `term:AITask [confirmed] #1` 开头,并包含 `created`
|
||||
|
||||
### 断言结论
|
||||
|
||||
- 新增 entry 后无需额外同步即可被搜索到
|
||||
- alias 可参与搜索命中
|
||||
- 事件历史足以追溯 durable knowledge 的创建来源
|
||||
|
||||
## case: ingest-search-list-across-sections
|
||||
|
||||
### 用例意义
|
||||
|
||||
验证 `ingest -> search -> list` 可以把 `docs/ai` Markdown 中的多个 section 转成可搜索、可枚举的知识条目。
|
||||
|
||||
### 前置条件
|
||||
|
||||
- `TMPDIR/repo` 是一个已提交初始 commit 的 Git 仓库
|
||||
- `TMPDIR/repo/docs/ai/repo-memory.md` 包含 `Module Map` 与 `Danger Zones` 等 section
|
||||
- 目标数据库路径尚未初始化也可,因为该用例验证 `ingest` 的自动 schema bootstrap
|
||||
|
||||
### 输入
|
||||
|
||||
```bash
|
||||
repo-memory ingest --db TMPDIR/repo-memory.db --repo TMPDIR/repo
|
||||
repo-memory search --db TMPDIR/repo-memory.db --repo repo --query "gateway"
|
||||
repo-memory list --db TMPDIR/repo-memory.db --repo repo
|
||||
```
|
||||
|
||||
### 预期输出
|
||||
|
||||
- `ingest` 输出 `ingested 1 docs from ABS_REPO`
|
||||
- `search` 命中从 `Module Map` 导入的 section
|
||||
- `list` 至少包含 `module:repo-memory:module-map` 与 `danger:repo-memory:danger-zones`
|
||||
|
||||
### 断言结论
|
||||
|
||||
- 一个 Markdown 文件可以导出多个 durable knowledge entry
|
||||
- 导入 entry 默认状态为 `confirmed`
|
||||
- `ingest` 既完成导入,也完成 repo 注册与 schema 初始化
|
||||
|
||||
## case: add-link-and-resolve-related-entry
|
||||
|
||||
### 用例意义
|
||||
|
||||
验证两个 entry 可以通过 `link` 建立关系,同时各自的历史记录仍可独立读取。
|
||||
|
||||
### 前置条件
|
||||
|
||||
- 空数据库已完成 `init`
|
||||
- 同一 repo 下已存在 `term:AITask` 与 `chain:ai-insight.get` 两条 entry
|
||||
|
||||
### 输入
|
||||
|
||||
```bash
|
||||
repo-memory link --db TMPDIR/repo-memory.db --from-id 1 --to-id 2 --relation related_to
|
||||
sqlite3 TMPDIR/repo-memory.db "SELECT relation FROM knowledge_links WHERE from_entry_id = 1 AND to_entry_id = 2;"
|
||||
repo-memory events --db TMPDIR/repo-memory.db --id 1
|
||||
repo-memory events --db TMPDIR/repo-memory.db --id 2
|
||||
```
|
||||
|
||||
### 预期输出
|
||||
|
||||
- `link` 输出 `linked #1 -[related_to]-> #2`
|
||||
- SQL 查询返回一行 `related_to`
|
||||
- 两个 `events` 调用仍能分别读取各自历史
|
||||
|
||||
### 断言结论
|
||||
|
||||
- `link` 的副作用被持久化,而不是只回显成功文本
|
||||
- entry 关系与 entry 历史是两个独立维度
|
||||
|
||||
## case: verify-downgrades-after-repo-change
|
||||
|
||||
### 用例意义
|
||||
|
||||
验证 `add -> verify -> list -> events` 在 repo 内容变更后会把已确认知识降级到需要复核或过期状态。
|
||||
|
||||
### 前置条件
|
||||
|
||||
- `TMPDIR/repo` 是一个已提交初始 commit 的 Git 仓库
|
||||
- 已存在一个 `confirmed` entry,硬依赖 `TMPDIR/repo/foo.txt`
|
||||
- 在 `verify` 前,`foo.txt` 已被修改或删除
|
||||
|
||||
### 输入
|
||||
|
||||
```bash
|
||||
repo-memory verify --db TMPDIR/repo-memory.db --repo TMPDIR/repo
|
||||
repo-memory list --db TMPDIR/repo-memory.db --repo repo
|
||||
repo-memory events --db TMPDIR/repo-memory.db --id 1
|
||||
```
|
||||
|
||||
### 预期输出
|
||||
|
||||
- `verify` 输出包含 `verified 1 entries`
|
||||
- `list` 中相应 entry 状态变为 `needs_review` 或 `stale`
|
||||
- `events` 中新增 `downgraded` 或 `marked_stale` 事件
|
||||
|
||||
### 断言结论
|
||||
|
||||
- `verify` 会根据 repo 当前状态重新评估 durable knowledge
|
||||
- 状态变化不仅更新当前 entry,也会追加历史事件供后续审计
|
||||
Reference in New Issue
Block a user