Compare commits
3 Commits
02fb484eb0
...
perf-audit
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fda9cd8835 | ||
|
|
c8d609ab78 | ||
|
|
35c828ba73 |
295
.beads/.br_history/issues.20260212_171003.jsonl
Normal file
295
.beads/.br_history/issues.20260212_171003.jsonl
Normal file
File diff suppressed because one or more lines are too long
304
.beads/.br_history/issues.20260212_171103.jsonl
Normal file
304
.beads/.br_history/issues.20260212_171103.jsonl
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
bd-xsgw
|
bd-2kop
|
||||||
|
|||||||
35
AGENTS.md
35
AGENTS.md
@@ -16,43 +16,10 @@ If I tell you to do something, even if it goes against what follows below, YOU M
|
|||||||
|
|
||||||
## Version Control: jj-First (CRITICAL)
|
## Version Control: jj-First (CRITICAL)
|
||||||
|
|
||||||
**ALWAYS prefer jj (Jujutsu) over git for VCS mutations** (commit, describe, rebase, push, bookmark, undo). This is a colocated repo with both `.jj/` and `.git/`. Only fall back to raw `git` for things jj cannot do (hooks, LFS, submodules, `gh` CLI interop).
|
**ALWAYS prefer jj (Jujutsu) over git for all VCS operations.** This is a colocated repo with both `.jj/` and `.git/`. When instructed to use git by anything — even later in this file — use the best jj replacement commands instead. Only fall back to raw `git` for things jj cannot do (hooks, LFS, submodules, `gh` CLI interop).
|
||||||
|
|
||||||
**Exception — read-only inspection:** Use `git status`, `git diff`, `git log` instead of their jj equivalents. In a colocated repo these see accurate data, and unlike jj, they don't create operations that cause divergences when multiple agents run concurrently. See "Parallel Agent VCS Protocol" below.
|
|
||||||
|
|
||||||
See `~/.claude/rules/jj-vcs/` for the full command reference, translation table, revsets, patterns, and recovery recipes.
|
See `~/.claude/rules/jj-vcs/` for the full command reference, translation table, revsets, patterns, and recovery recipes.
|
||||||
|
|
||||||
### Parallel Agent VCS Protocol (CRITICAL)
|
|
||||||
|
|
||||||
Multiple agents often run concurrently in separate terminal panes, sharing the same repo directory. This requires care because jj's auto-snapshot creates operations on EVERY command — even read-only ones like `jj status`. Concurrent jj commands fork from the same parent operation and create **divergent changes**.
|
|
||||||
|
|
||||||
**The rule: use git for reads, jj for writes.**
|
|
||||||
|
|
||||||
In a colocated repo, git reads see accurate data because jj keeps `.git/` in sync.
|
|
||||||
|
|
||||||
| Operation | Use | Why |
|
|
||||||
|-----------|-----|-----|
|
|
||||||
| Check status | `git status` | No jj operation created |
|
|
||||||
| View diff | `git diff` | No jj operation created |
|
|
||||||
| Browse history | `git log` | No jj operation created |
|
|
||||||
| Commit work | `jj commit -m "msg"` | jj mutation (better UX) |
|
|
||||||
| Update description | `jj describe -m "msg"` | jj mutation |
|
|
||||||
| Rebase | `jj rebase -d trunk()` | jj mutation |
|
|
||||||
| Push | `jj git push -b <name>` | jj mutation |
|
|
||||||
| Manage bookmarks | `jj bookmark set ...` | jj mutation |
|
|
||||||
| Undo a mistake | `jj undo` | jj mutation |
|
|
||||||
|
|
||||||
**NEVER run `jj status`, `jj diff`, `jj log`, or `jj show` when other agents may be active** — these trigger snapshots that cause divergences.
|
|
||||||
|
|
||||||
**If using Claude Code's built-in agent teams:** Only the team lead runs ANY VCS commands (git or jj). Workers only edit files via Edit/Write tools and do NOT run "Landing the Plane".
|
|
||||||
|
|
||||||
**Resolving divergences if they occur:**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
jj log -r 'divergent()' # Find divergent changes
|
|
||||||
jj abandon <unwanted-commit-id> # Keep the version you want
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Irreversible Git & Filesystem Actions — DO NOT EVER BREAK GLASS
|
## Irreversible Git & Filesystem Actions — DO NOT EVER BREAK GLASS
|
||||||
|
|||||||
@@ -185,6 +185,7 @@ const COMMAND_FLAGS: &[(&str, &[&str])] = &[
|
|||||||
"--no-detail",
|
"--no-detail",
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
("drift", &["--threshold", "--project"]),
|
||||||
(
|
(
|
||||||
"init",
|
"init",
|
||||||
&[
|
&[
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ pub fn strip_schemas(commands: &mut serde_json::Value) {
|
|||||||
for (_cmd_name, cmd) in map.iter_mut() {
|
for (_cmd_name, cmd) in map.iter_mut() {
|
||||||
if let Some(obj) = cmd.as_object_mut() {
|
if let Some(obj) = cmd.as_object_mut() {
|
||||||
obj.remove("response_schema");
|
obj.remove("response_schema");
|
||||||
|
obj.remove("example_output");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
29
src/main.rs
29
src/main.rs
@@ -2065,6 +2065,7 @@ struct RobotDocsData {
|
|||||||
version: String,
|
version: String,
|
||||||
description: String,
|
description: String,
|
||||||
activation: RobotDocsActivation,
|
activation: RobotDocsActivation,
|
||||||
|
quick_start: serde_json::Value,
|
||||||
commands: serde_json::Value,
|
commands: serde_json::Value,
|
||||||
/// Deprecated command aliases (old -> new)
|
/// Deprecated command aliases (old -> new)
|
||||||
aliases: serde_json::Value,
|
aliases: serde_json::Value,
|
||||||
@@ -2168,6 +2169,7 @@ fn handle_robot_docs(robot_mode: bool, brief: bool) -> Result<(), Box<dyn std::e
|
|||||||
"meta": {"elapsed_ms": "int"}
|
"meta": {"elapsed_ms": "int"}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"example_output": {"list": {"ok":true,"data":{"issues":[{"iid":3864,"title":"Switch Health Card","state":"opened","status_name":"In progress","labels":["customer:BNSF"],"assignees":["teernisse"],"discussion_count":12,"updated_at_iso":"2026-02-12T..."}],"total_count":1,"showing":1},"meta":{"elapsed_ms":42}}},
|
||||||
"fields_presets": {"minimal": ["iid", "title", "state", "updated_at_iso"]}
|
"fields_presets": {"minimal": ["iid", "title", "state", "updated_at_iso"]}
|
||||||
},
|
},
|
||||||
"mrs": {
|
"mrs": {
|
||||||
@@ -2186,6 +2188,7 @@ fn handle_robot_docs(robot_mode: bool, brief: bool) -> Result<(), Box<dyn std::e
|
|||||||
"meta": {"elapsed_ms": "int"}
|
"meta": {"elapsed_ms": "int"}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"example_output": {"list": {"ok":true,"data":{"mrs":[{"iid":200,"title":"Add throw time chart","state":"opened","draft":false,"author_username":"teernisse","target_branch":"main","source_branch":"feat/throw-time","reviewers":["cseiber"],"discussion_count":5,"updated_at_iso":"2026-02-11T..."}],"total_count":1,"showing":1},"meta":{"elapsed_ms":38}}},
|
||||||
"fields_presets": {"minimal": ["iid", "title", "state", "updated_at_iso"]}
|
"fields_presets": {"minimal": ["iid", "title", "state", "updated_at_iso"]}
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
@@ -2197,6 +2200,7 @@ fn handle_robot_docs(robot_mode: bool, brief: bool) -> Result<(), Box<dyn std::e
|
|||||||
"data": {"results": "[{document_id:int, source_type:string, title:string, snippet:string, score:float, url:string?, author:string?, created_at:string?, updated_at:string?, project_path:string, labels:[string], paths:[string]}]", "total_results": "int", "query": "string", "mode": "string", "warnings": "[string]"},
|
"data": {"results": "[{document_id:int, source_type:string, title:string, snippet:string, score:float, url:string?, author:string?, created_at:string?, updated_at:string?, project_path:string, labels:[string], paths:[string]}]", "total_results": "int", "query": "string", "mode": "string", "warnings": "[string]"},
|
||||||
"meta": {"elapsed_ms": "int"}
|
"meta": {"elapsed_ms": "int"}
|
||||||
},
|
},
|
||||||
|
"example_output": {"ok":true,"data":{"query":"throw time","mode":"hybrid","total_results":3,"results":[{"document_id":42,"source_type":"issue","title":"Switch Health Card","score":0.92,"snippet":"...throw time data from BNSF...","project_path":"vs/typescript-code"}],"warnings":[]},"meta":{"elapsed_ms":85}},
|
||||||
"fields_presets": {"minimal": ["document_id", "title", "source_type", "score"]}
|
"fields_presets": {"minimal": ["document_id", "title", "source_type", "score"]}
|
||||||
},
|
},
|
||||||
"count": {
|
"count": {
|
||||||
@@ -2306,6 +2310,7 @@ fn handle_robot_docs(robot_mode: bool, brief: bool) -> Result<(), Box<dyn std::e
|
|||||||
},
|
},
|
||||||
"meta": {"elapsed_ms": "int"}
|
"meta": {"elapsed_ms": "int"}
|
||||||
},
|
},
|
||||||
|
"example_output": {"expert": {"ok":true,"data":{"mode":"expert","result":{"experts":[{"username":"teernisse","score":42,"note_count":15,"diff_note_count":8}]}},"meta":{"elapsed_ms":65}}},
|
||||||
"fields_presets": {
|
"fields_presets": {
|
||||||
"expert_minimal": ["username", "score"],
|
"expert_minimal": ["username", "score"],
|
||||||
"workload_minimal": ["entity_type", "iid", "title", "state"],
|
"workload_minimal": ["entity_type", "iid", "title", "state"],
|
||||||
@@ -2319,7 +2324,28 @@ fn handle_robot_docs(robot_mode: bool, brief: bool) -> Result<(), Box<dyn std::e
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// --brief: strip response_schema from every command (~60% smaller)
|
let quick_start = serde_json::json!({
|
||||||
|
"glab_equivalents": [
|
||||||
|
{ "glab": "glab issue list", "lore": "lore -J issues -n 50", "note": "Richer: includes labels, status, closing MRs, discussion counts" },
|
||||||
|
{ "glab": "glab issue view 123", "lore": "lore -J issues 123", "note": "Includes full discussions, work-item status, cross-references" },
|
||||||
|
{ "glab": "glab issue list -l bug", "lore": "lore -J issues --label bug", "note": "AND logic for multiple --label flags" },
|
||||||
|
{ "glab": "glab mr list", "lore": "lore -J mrs", "note": "Includes draft status, reviewers, discussion counts" },
|
||||||
|
{ "glab": "glab mr view 456", "lore": "lore -J mrs 456", "note": "Includes discussions, review threads, source/target branches" },
|
||||||
|
{ "glab": "glab mr list -s opened", "lore": "lore -J mrs -s opened", "note": "States: opened, merged, closed, locked, all" },
|
||||||
|
{ "glab": "glab api '/projects/:id/issues'", "lore": "lore -J issues -p project", "note": "Fuzzy project matching (suffix or substring)" }
|
||||||
|
],
|
||||||
|
"lore_exclusive": [
|
||||||
|
"search: FTS5 + vector hybrid search across all entities",
|
||||||
|
"who: Expert/workload/reviews analysis per file path or person",
|
||||||
|
"timeline: Chronological event reconstruction across entities",
|
||||||
|
"stats: Database statistics with document/note/discussion counts",
|
||||||
|
"count: Entity counts with state breakdowns",
|
||||||
|
"embed: Generate vector embeddings for semantic search via Ollama"
|
||||||
|
],
|
||||||
|
"read_write_split": "lore = ALL reads (issues, MRs, search, who, timeline, intelligence). glab = ALL writes (create, update, approve, merge, CI/CD)."
|
||||||
|
});
|
||||||
|
|
||||||
|
// --brief: strip response_schema and example_output from every command (~60% smaller)
|
||||||
let mut commands = commands;
|
let mut commands = commands;
|
||||||
if brief {
|
if brief {
|
||||||
strip_schemas(&mut commands);
|
strip_schemas(&mut commands);
|
||||||
@@ -2422,6 +2448,7 @@ fn handle_robot_docs(robot_mode: bool, brief: bool) -> Result<(), Box<dyn std::e
|
|||||||
env: "LORE_ROBOT=1".to_string(),
|
env: "LORE_ROBOT=1".to_string(),
|
||||||
auto: "Non-TTY stdout".to_string(),
|
auto: "Non-TTY stdout".to_string(),
|
||||||
},
|
},
|
||||||
|
quick_start,
|
||||||
commands,
|
commands,
|
||||||
aliases,
|
aliases,
|
||||||
exit_codes,
|
exit_codes,
|
||||||
|
|||||||
Reference in New Issue
Block a user