diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2d11bdd..8a9ca62 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -30,8 +30,8 @@ pnpm bootstrap ``` `pnpm bootstrap` runs `mise install && pnpm install`. Without mise, install the Node.js 22 release -pinned in `mise.toml` and pnpm, then run `pnpm install` directly. Published packages retain their -documented Node.js 20 runtime support; the repository toolchain itself requires Node.js 22. +pinned in `mise.toml` and pnpm, then run `pnpm install` directly. The published packages and the +repository toolchain require Node.js 22 or later. Activate mise in your shell (`mise activate`, per the [mise docs](https://mise.jdx.dev/getting-started.html)) so that entering this repository puts the diff --git a/README.md b/README.md index a6c9172..3557490 100644 --- a/README.md +++ b/README.md @@ -164,19 +164,21 @@ flowchart LR D --> E["Ready private index"] ``` -Git-backed teams build one private index per developer and use one command after reviewed changes -land through a merge request: +Git-backed teams build one private index per developer. The current branch upstream is the only +declared authority: Git carries the reviewed change, Ragmir refreshes the local evidence. ```bash pnpm exec rgr team sync ``` -Ragmir fetches the current branch upstream, fast-forwards only a clean non-divergent branch, then -reindexes changed sources incrementally. Dirty, ahead, diverged, detached, offline, and no-upstream -states never rewrite history and return one action. Use `--no-pull` to keep branch updates manual or -`--check` to preview. Advanced `team snapshot` and `team compare` diagnostics remain available for -non-Git sources or exact drift analysis, including existing v2.19 snapshots. Detailed safeguards -live in the +1. Open and review a pull request (or merge request). +2. Merge it into the declared upstream. +3. Run `rgr team sync` on each workstation that needs fresh evidence. + +Ragmir fast-forwards only a clean non-divergent branch and reindexes changed sources incrementally. +Otherwise it leaves history and the valid index alone, then returns one action. `--no-pull` keeps +branch updates manual and `--check` previews. Snapshots are an advanced fallback for non-Git sources +or exact drift analysis, including existing v2.19 snapshots. Detailed safeguards live in the [team guide](./docs/agent-integration.md#team-knowledge-bases) and [configuration reference](./docs/configuration.md#stable-team-source-configuration). diff --git a/docs/agent-integration.md b/docs/agent-integration.md index a629da3..20364b2 100644 --- a/docs/agent-integration.md +++ b/docs/agent-integration.md @@ -66,41 +66,69 @@ from different bases labeled rather than silently merging citations. ## Team knowledge bases -Ragmir keeps one private local index per developer. For a Git-backed team, check out the branch the -team declared authoritative, configure its upstream once, then use one command: +Ragmir keeps one private local index per developer. For a Git-backed team, the current branch +upstream is the only declared authority. Configure it once, then use one command: ```bash rgr team sync ``` -The command fetches only that upstream branch, compares Git history, and fast-forwards the checked -out branch only when the worktree is clean, the local branch has no unpublished commit, and history -has not diverged. It then runs incremental ingestion and reports `current`, `updated`, or one clear -action. It never stashes, resets, rebases, creates a merge commit, deletes the active index, or -chooses another branch. +### The everyday workflow -This keeps the normal team loop small: +```mermaid +flowchart LR + A["Push a reviewable change"] --> B["Merge to the declared upstream"] + B --> C["rgr team sync"] + C --> D["Safe fast-forward, if possible"] + D --> E["Incremental local ingest"] + E --> F["Ready private index"] +``` -1. A developer pushes a branch and opens or updates the merge request. +1. A developer pushes a branch and opens or updates a pull request (or merge request). 2. The team reviews and merges it into the declared upstream branch. -3. Other developers run `rgr team sync`; safe updates and local reindexing happen together. +3. Other developers run `rgr team sync`; source updates and local reindexing happen together. + +Git already shows what changed and where review is needed. Ragmir does not add labels, snapshots, +or another source of truth to this normal path. + +| Result | What Ragmir does | +| --- | --- | +| `current` | Keeps the checked-out sources and local index because they are already aligned. | +| `updated` | Fetches only the declared upstream, fast-forwards safely, then ingests changed sources. | +| Needs action | Leaves Git history and the active index untouched, then explains the first next step. | + +The automatic path fetches only that upstream and fast-forwards only when the worktree is clean, +the local branch has no unpublished commits, and history has not diverged. It never stashes, resets, +rebases, creates a merge commit, chooses another branch, or deletes the active index. + +### Choose the sync mode + +| Need | Command | Effect | +| --- | --- | --- | +| Normal team update | `rgr team sync` | Safely update from upstream and ingest incrementally. | +| Keep Git updates manual | `rgr team sync --no-pull` | Fetch and compare, but do not change the checked-out branch. | +| Preview only | `rgr team sync --check` | Report Git and index state without changing either one. | +| Work offline | `rgr team sync --no-fetch` | Use cached Git state and local sources only. | +| Enforce in automation | `rgr team sync --strict --json` | Return a typed report and fail unless freshness and readiness are proven. | -Use `--no-pull` to fetch and compare while keeping branch updates manual. Use `--check` to preview -without changing the worktree or index, `--no-fetch` for an explicitly offline run, `--strict` in -CI, and `--json` for automation. A dirty, ahead, diverged, detached, or untracked branch is never -rewritten. A failed fetch keeps the last valid local index available and reports that upstream -freshness is unverified. A failed ingestion keeps the previous validated index instead of deleting -it first. +Dirty, ahead, diverged, detached, untracked, or no-upstream branches are never rewritten. A failed +fetch keeps the last valid index and marks upstream freshness as unverified. A failed ingestion also +preserves the previous validated index. Resolve the Git state through the normal pull-request or +merge-request workflow, then run the same command again. The ignored `.ragmir/config.json` remains local. If every workstation needs the exact same source contract, version a reviewed template in the repository and apply it during setup. `rgr team sync` synchronizes tracked sources through Git; it does not commit or distribute private Ragmir state. -### Advanced drift diagnostics +### When exact drift diagnosis is genuinely needed + +Snapshots are an advanced fallback for a non-Git authority, such as Drive, or for a specific +configuration and per-file investigation. They are not a prerequisite for ordinary Git teams. -Snapshots remain available for a non-Git authority such as Drive, or when the team needs an exact -configuration and per-file comparison. They are not part of the normal Git workflow. On one -authorized workstation: +
+Compare two authorized snapshots without sharing source text + +On one authorized workstation: ```bash rgr team snapshot --label local --output .ragmir/team/local.json @@ -135,6 +163,8 @@ ingestion. Do not synchronize `.ragmir/storage/` between active writers. A team bootstrap can call `initProject`, `addSourceEntries`, and `syncTeamKnowledge`; each workstation still owns its index. +
+ ### Agent behavior on team drift An agent using the bundled Ragmir skill should run `rgr team sync --json` before relying on a @@ -144,7 +174,7 @@ the last valid local index may be older than upstream. It must never resolve Git reset, rebase, or overwrite source files. Snapshot comparison remains the advanced fallback for an authorized non-Git source or exact drift investigation. -## MCP tools +## Use Ragmir through MCP The server exposes `ragmir_status`, `ragmir_route_prompt`, `ragmir_search`, `ragmir_ask`, `ragmir_research`, `ragmir_expand`, `ragmir_audit`, `ragmir_evaluate`, `ragmir_usage_report`, and @@ -164,6 +194,8 @@ The TypeScript `sources({ offset, limit })` method can request later pages direc manifest file snapshot without materializing the complete source list; its default page remains 50 files. +### Retrieve bounded evidence + Use compact retrieval first, then pass a returned citation to `ragmir_expand` when the agent needs the exact chunk or a bounded neighbor window. Search, ask, research, expansion, audit, and evaluation accept `maxBytes`. Variable-size tool and resource JSON is bounded by `mcpMaxOutputBytes` and an @@ -177,6 +209,9 @@ size, audit detail, and returned evaluation case details, while keeping aggregat `ragmir_ask` returns cited evidence, not a model generated answer. A cloud agent can receive returned passages, so choose that handoff only when it matches the corpus's confidentiality requirements. +
+Advanced: response contracts, safety annotations, and server lifecycle + Every tool advertises non-destructive behavior to compatible clients. Search, ask, research, and evaluation conservatively advertise open-world behavior because explicitly enabled semantic models may download public weights. The pure prompt router, security audit, and usage report also advertise @@ -202,6 +237,8 @@ before and after the call. Ragmir does not open an HTTP port; applications that transport own its authentication and authorization boundary. +
+ ## Verify ```bash diff --git a/docs/cli-reference.md b/docs/cli-reference.md index 7271fbb..c36bebd 100644 --- a/docs/cli-reference.md +++ b/docs/cli-reference.md @@ -83,23 +83,36 @@ report records both configured and consumed budgets. rgr team sync ``` -`team sync` treats the current branch upstream as the declared source of truth. It fetches that -single branch, fast-forwards only a clean branch with no local-only commits or divergence, then runs -incremental ingestion. Git authentication is non-interactive and each Git command is bounded. A -dirty, ahead, diverged, detached, or no-upstream state never changes branch history and returns one -recommended action. Fetch and ingestion failures keep the previous valid local index available -when one exists. +Use this after reviewed source changes merge into the current branch upstream. That upstream is the +declared authority, and Git remains the place where the team reviews differences. `team sync` +fetches only that branch, fast-forwards only a clean non-divergent history with no local-only +commits, then ingests changed sources incrementally. Git authentication is non-interactive and each +Git command is bounded. + +| Result | Meaning | +| --- | --- | +| `current` | The checked-out sources and private local index already match upstream. | +| `updated` | A safe fast-forward and incremental ingest completed. | +| Needs action | Git history and the active index were preserved; follow the one recommended action. | | Option | Behavior | | --- | --- | -| `--no-pull` | Fetch and compare, but never update the checked-out branch. | +| `--no-pull` | Fetch and compare, but keep branch updates manual. | | `--no-fetch` | Avoid network access and use only cached Git state plus local sources. | | `--check` | Fetch and report without changing the worktree or index. | | `--git-timeout-ms N` | Bound each Git command, from 1 ms to 300,000 ms. | | `--strict` | Exit with code 1 unless upstream freshness and local index readiness are proven. | | `--json` | Return the complete typed report. | -Snapshots are an advanced fallback for non-Git sources or exact drift investigation: +A dirty, ahead, diverged, detached, or no-upstream state never rewrites history. Fetch and ingestion +failures preserve the previous valid local index when one exists. Resolve the Git state through the +normal pull-request or merge-request workflow, then rerun the same command. + +
+Advanced: diagnose exact drift or a non-Git authority + +Snapshots are not part of the normal Git workflow. Use them for a non-Git authority or a specific +per-file comparison: ```bash rgr team snapshot --label local --output .ragmir/team/local.json @@ -120,6 +133,8 @@ do not require deleting or rebuilding the index. Snapshots written by Ragmir v2. v2.19.2 remain compatible. These advanced commands never change source files or decide which side is authoritative. +
+ ## Safe upgrades ```bash diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index 6123518..4fc9a22 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -76,7 +76,8 @@ updates must remain manual and `--check` for a no-worktree-change preview. The active `.ragmir/config.json` is intentionally local and ignored. If results still differ after Git is current, verify that both workstations use the same reviewed source-contract template and -Ragmir version. For an exact diagnosis or a non-Git authority, use the advanced snapshot flow: +Ragmir version. Do not start with snapshots: use them only for an exact diagnosis or a non-Git +authority: ```bash rgr team snapshot --label local --output .ragmir/team/local.json diff --git a/packages/ragmir-core/src/team-sync.test.ts b/packages/ragmir-core/src/team-sync.test.ts index 82a7593..541659c 100644 --- a/packages/ragmir-core/src/team-sync.test.ts +++ b/packages/ragmir-core/src/team-sync.test.ts @@ -79,7 +79,7 @@ describe.sequential("team sync", () => { expect(await readFile(path.join(fixture.local, "docs", "decision.md"), "utf8")).toBe( "Local draft.\n", ) - }) + }, 15_000) it("should require the merge-request workflow when local and upstream histories diverge", async () => { const fixture = await createGitFixture() @@ -153,7 +153,7 @@ describe.sequential("team sync", () => { "Check mode did not change the worktree or refresh the index.", ) expect(await git(fixture.local, ["rev-parse", "HEAD"])).toBe(headBefore) - }) + }, 15_000) it("should avoid remote access and branch updates when fetch is disabled", async () => { const fixture = await createGitFixture()