Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .claude/agent-memory/archgate-developer/MEMORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ Non-enforceable lessons — environment/CI/platform quirks no static rule can re
- **`oxfmt` formats markdown too — run `bun run format` after editing any `.md`, including ADRs** — `format:check` (part of `bun run validate` and the CI "Lint, Test & Check" job) runs `oxfmt --check .` over ALL files, not just `.ts`. It normalizes markdown (e.g., emphasis `*word*` → `_word_`). The `adr-author` skill writes ADR markdown but does NOT auto-format it, so ADR edits frequently fail CI `format:check` even when the TS changes are clean. Always run `bun run format` before committing ADR/markdown edits. Tripped CI on PR #372 (ARCH-005 edit).
- **YAML double-quoted strings require escaped backslashes for Windows paths in tests** — YAML interprets `\` as an escape character inside double-quoted strings. Writing `cwd: "E:\project"` silently corrupts the parsed value because `\p` is not a valid escape sequence. Fix: use `JSON.stringify(path)` to produce properly escaped YAML values (e.g., `cwd: ${JSON.stringify(cwd)}`). JSON and YAML double-quoted strings share the same escape syntax. Encountered in Copilot CLI session-context tests (`workspace.yaml` with Windows paths).
- **`Bun.Glob.match()` triggers oxlint `prefer-regexp-test`** — `Bun.Glob.match()` returns a boolean (not a RegExp), but oxlint can't tell. Suppress with `// oxlint-disable-next-line prefer-regexp-test -- Bun.Glob.match() returns boolean, not RegExp`.
- **Live `opencode.db` can't be opened `readonly: true` while opencode runs** — `new Database(path, { readonly: true })` fails with `SQLITE_CANTOPEN` (errno 14) on the live WAL-mode DB (`~/.local/share/opencode/opencode.db`). To inspect real data, copy `opencode.db` + `.db-wal` + `.db-shm` to a temp dir and open the copy. Data model facts load-bearing for `session-context opencode`: sub-agent runs are child sessions (`parent_id` set) sharing the parent's `directory`, and opencode skills run INLINE in the calling session (no own session row) — recency selection must filter `parent_id IS NULL` (fixed 2026-07-01; `--root` resolves a `--session-id` child to its top-level ancestor).
- **The distributed opencode lessons-learned skill references session-context CLI flags — sequence releases** — the skill instructs `archgate session-context opencode --root` (was `--skip 1`, which read sub-agent transcripts). When changing session-context CLI semantics, update the shipped skill in the same effort AND sequence releases: the CLI ships the flag first, the plugin follows — a skill referencing a flag the installed CLI lacks dies with "unknown option". Don't hand-edit the installed copy under `~/.config/opencode/skills/` before the CLI release.
- **Verify haiku reviewer findings against the cited ADR's text before blocking** — A haiku review sub-agent reported "await on a synchronous helper" as an ARCH-012 violation; ARCH-012 only mandates try-catch boundaries/exit codes and its automated rules passed. Re-read the cited ADR's Decision/Do's before accepting a FAIL; overrule misattributed style nits but still surface them as non-ADR notes. Recurred 2026-07-01: the same await-on-sync-helper nit came back self-labeled "ARCH-NONE" — a finding citing no ADR can never block.
- **Git Bash `/tmp` is invisible to Windows-native tools** — A bash redirect to `/tmp/x` writes into Git Bash's virtual mount, but Windows-native python/node then fail with `FileNotFoundError` on that path (gh.exe survives only because Git Bash rewrites path-looking arguments). When piping a file between bash and Windows-native tools, use a repo-relative path (and clean it up) or `$TMPDIR`.
- **oxlint `no-negated-condition`** — Always write ternaries with the positive condition first: `x === null ? A : B` not `x !== null ? B : A`. Applies to both `if/else` blocks and ternary expressions.
- **oxlint `no-unused-vars` on catch parameters** — Use bare `catch { }` (no parameter) when the caught error is not used. `catch (err) { }` with unused `err` triggers the rule.
- **oxlint `no-await-in-loop`** — Sequential `await` inside a `for` loop is flagged (warning). When the sequential order is intentional (e.g., build steps with per-step output), suppress with `// oxlint-disable-next-line no-await-in-loop -- <reason>`.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
name: project-session-context-skip-root-fix
description: opencode session-context --skip 1 sibling/inline-skill bug fixed 2026-07-01 (top-level default + --root ancestry walk); same class of bug likely still open for claude-code/cursor/copilot
metadata:
type: project
---

Fixed a real, reproduced bug in `archgate session-context opencode --skip 1`: it could return a completely unrelated sibling sub-agent's session transcript instead of the true parent/development session. Fix shipped 2026-07-01 (see `src/helpers/session-context-opencode.ts` and `src/commands/session-context/opencode.ts`): recency selection now only considers **top-level sessions** (`parent_id IS NULL`) by default, and a new `--root` flag walks the `parent_id` chain from a `--session-id` child session up to its top-level ancestor (cycle-guarded). Without `--session-id`, `--root` is an explicit alias for the new default.

**Why:** `readOpencodeSession`'s `--skip N` selected the Nth-most-recently-updated session sharing a project directory, ignoring opencode's real `session.parent_id` column entirely. This breaks in two ways: (1) the opencode `Skill` tool runs inline in the current session (no new session row), so "skip past my own session" skips past the actual parent instead; (2) sibling sub-agent sessions fanned out from the same parent (e.g. the `archgate:reviewer` skill's parallel domain-review agents) interleave in recency order with the parent, so `--skip 1` can land on any sibling. Verified this concretely against the user's real `~/.local/share/opencode/opencode.db`: a live `archgate-lessons-learned` skill invocation's `--skip 1` call returned the "General process ADR review" sub-agent's private transcript instead of the parent session.

Top-level filtering fixes the common case regardless of nesting depth or sibling count; `--session-id <child> --root` gives deterministic ancestry resolution when the caller knows a session inside the right conversation tree (relevant when several top-level sessions share a directory — recency alone can pick a different conversation's root). The distributed archgate editor plugin's opencode lessons-learned skill was updated to use `--root` instead of `--skip 1`.

**Open/unresolved:** The _same class_ of bug likely still affects the other 3 editors' lessons-learned skill guidance (`archgate session-context claude-code --skip 1`, `cursor --skip 1`). Live-reproduced for Claude Code: running `archgate session-context claude-code --skip 1` from within an inline Skill invocation returned an unrelated, unconnected past session (`6ee6f0a5-...` about "ExitWorktree"), not the current/parent conversation — because Claude Code's Skill tool also runs inline, so `--skip 1` skips past the correct (current) session file. Unlike opencode, Claude Code/Cursor have no `parent_id`-equivalent — sessions are flat per-conversation JSONL/directory files with no structural parent link, so the `--root` fix pattern doesn't directly transfer; a different fix (e.g. detecting "am I inline vs a real sub-agent" some other way, or defaulting to `--skip 0` for inline skill runs) would be needed. Not investigated for Copilot. This has NOT been fixed — flag to the user before doing more lessons-learned/reviewer work that depends on `--skip 1` being reliable for non-opencode editors.

**How to apply:** If asked to investigate "session context returns wrong data" for claude-code, cursor, or copilot, start here — this is the same architectural flaw already fixed once for opencode, not a new mystery.
21 changes: 15 additions & 6 deletions docs/public/llms-full.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4388,17 +4388,20 @@ archgate session-context cursor [options]

### archgate session-context opencode

Read the opencode session transcript for the project. Sessions are matched by the project `path` field in session metadata.
Read the opencode session transcript for the project. Sessions are matched by comparing the session `directory` field to the project root. opencode records sub-agent runs as child sessions that share the parent's directory — these are excluded from recency selection, so the most recent top-level session is always the main development session. Use `--session-id` to read a specific session, including a sub-agent child session.

When several top-level sessions exist for the same directory, recency selection picks the most recently updated one — which may not be the conversation you are part of. If you know a session ID inside the right conversation tree (for example, a sub-agent knows its own child session ID), pass `--session-id <id> --root` to resolve its top-level ancestor deterministically instead of relying on recency.

```bash
archgate session-context opencode [options]
```

| Option | Description |
| ------------------- | ------------------------------------------------------------------ |
| `--max-entries <n>` | Maximum entries to return (default: 200) |
| `--skip <n>` | Skip the N most recent sessions (useful when running as sub-agent) |
| `--session-id <id>` | Specific session ID to read |
| Option | Description |
| ------------------- | ------------------------------------------------------------------------------------------------------ |
| `--max-entries <n>` | Maximum entries to return (default: 200) |
| `--skip <n>` | Skip the N most recent top-level sessions (sub-agent sessions always excluded) |
| `--session-id <id>` | Specific session ID to read |
| `--root` | Resolve to the top-level (root) session — with `--session-id`, walks up from a sub-agent child session |
Comment thread
coderabbitai[bot] marked this conversation as resolved.

## Examples

Expand Down Expand Up @@ -4432,6 +4435,12 @@ Read the parent session (skip the sub-agent's own session):
archgate session-context claude-code --skip 1
```

Resolve an opencode sub-agent child session to its top-level ancestor:

```bash
archgate session-context opencode --session-id ses_child123 --root
```

---

## Reference: archgate telemetry
Expand Down
21 changes: 15 additions & 6 deletions docs/src/content/docs/nb/reference/cli/session-context.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,20 @@ archgate session-context cursor [options]

### archgate session-context opencode

Les opencode-sesjonsloggen for prosjektet. Sesjoner matches etter prosjektets `path`-felt i sesjonsmetadataene.
Les opencode-sesjonsloggen for prosjektet. Sesjoner matches ved å sammenligne sesjonens `directory`-felt med prosjektroten. opencode lagrer underagent-kjøringer som barnesesjoner som deler foreldrenes katalog — disse ekskluderes fra utvalget etter nylighet, slik at den nyeste toppnivåsesjonen alltid er hovedutviklingssesjonen. Bruk `--session-id` for å lese en bestemt sesjon, inkludert en underagent-barnesesjon.

Når flere toppnivåsesjoner finnes for samme katalog, velger nylighetsutvalget den som sist ble oppdatert — som kanskje ikke er samtalen du er en del av. Hvis du kjenner en sesjons-ID i riktig samtaletre (for eksempel kjenner en underagent sin egen barnesesjons-ID), send `--session-id <id> --root` for å løse opp toppnivåforelderen deterministisk i stedet for å stole på nylighet.

```bash
archgate session-context opencode [options]
```

| Valg | Beskrivelse |
| ------------------- | ------------------------------------------------------------------- |
| `--max-entries <n>` | Maksimalt antall oppføringer å returnere (standard: 200) |
| `--skip <n>` | Hopp over de N nyeste sesjonene (nyttig ved kjøring som underagent) |
| `--session-id <id>` | Spesifikk sesjons-ID å lese |
| Valg | Beskrivelse |
| ------------------- | ----------------------------------------------------------------------------------------------------- |
| `--max-entries <n>` | Maksimalt antall oppføringer å returnere (standard: 200) |
| `--skip <n>` | Hopp over de N nyeste toppnivåsesjonene (underagentsesjoner ekskluderes alltid) |
| `--session-id <id>` | Spesifikk sesjons-ID å lese |
| `--root` | Løs opp til toppnivåsesjonen (rot) — med `--session-id` gås det oppover fra en underagent-barnesesjon |

## Eksempler

Expand Down Expand Up @@ -97,3 +100,9 @@ Les foreldresesjonen (hopp over underagentens egen sesjon):
```bash
archgate session-context claude-code --skip 1
```

Løs opp en underagent-barnesesjon i opencode til dens toppnivåforelder:

```bash
archgate session-context opencode --session-id ses_child123 --root
```
21 changes: 15 additions & 6 deletions docs/src/content/docs/pt-br/reference/cli/session-context.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,20 @@ archgate session-context cursor [options]

### archgate session-context opencode

Lê a transcrição de sessão do opencode para o projeto. Sessões são correspondidas pelo campo `path` do projeto nos metadados da sessão.
Lê a transcrição de sessão do opencode para o projeto. Sessões são correspondidas comparando o campo `directory` da sessão com a raiz do projeto. O opencode registra execuções de sub-agentes como sessões filhas que compartilham o diretório da sessão pai — elas são excluídas da seleção por recência, de modo que a sessão de nível superior mais recente é sempre a sessão principal de desenvolvimento. Use `--session-id` para ler uma sessão específica, incluindo uma sessão filha de sub-agente.

Quando existem várias sessões de nível superior para o mesmo diretório, a seleção por recência escolhe a atualizada mais recentemente — que pode não ser a conversa da qual você faz parte. Se você conhece um ID de sessão dentro da árvore de conversa correta (por exemplo, um sub-agente conhece o ID da sua própria sessão filha), passe `--session-id <id> --root` para resolver o ancestral de nível superior de forma determinística em vez de depender da recência.

```bash
archgate session-context opencode [options]
```

| Opção | Descrição |
| ------------------- | ------------------------------------------------------------------- |
| `--max-entries <n>` | Máximo de entradas a retornar (padrão: 200) |
| `--skip <n>` | Pular as N sessões mais recentes (útil ao executar como sub-agente) |
| `--session-id <id>` | ID específico da sessão a ser lida |
| Opção | Descrição |
| ------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `--max-entries <n>` | Máximo de entradas a retornar (padrão: 200) |
| `--skip <n>` | Pular as N sessões de nível superior mais recentes (sessões de sub-agente são sempre excluídas) |
| `--session-id <id>` | ID específico da sessão a ser lida |
| `--root` | Resolve para a sessão de nível superior (raiz) — com `--session-id`, sobe a partir de uma sessão filha de sub-agente |
Comment thread
coderabbitai[bot] marked this conversation as resolved.

## Exemplos

Expand Down Expand Up @@ -97,3 +100,9 @@ Ler a sessão pai (pular a sessão do sub-agente):
```bash
archgate session-context claude-code --skip 1
```

Resolver uma sessão filha de sub-agente do opencode para seu ancestral de nível superior:

```bash
archgate session-context opencode --session-id ses_child123 --root
```
21 changes: 15 additions & 6 deletions docs/src/content/docs/reference/cli/session-context.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,20 @@ archgate session-context cursor [options]

### archgate session-context opencode

Read the opencode session transcript for the project. Sessions are matched by the project `path` field in session metadata.
Read the opencode session transcript for the project. Sessions are matched by comparing the session `directory` field to the project root. opencode records sub-agent runs as child sessions that share the parent's directory — these are excluded from recency selection, so the most recent top-level session is always the main development session. Use `--session-id` to read a specific session, including a sub-agent child session.

When several top-level sessions exist for the same directory, recency selection picks the most recently updated one — which may not be the conversation you are part of. If you know a session ID inside the right conversation tree (for example, a sub-agent knows its own child session ID), pass `--session-id <id> --root` to resolve its top-level ancestor deterministically instead of relying on recency.

```bash
archgate session-context opencode [options]
```

| Option | Description |
| ------------------- | ------------------------------------------------------------------ |
| `--max-entries <n>` | Maximum entries to return (default: 200) |
| `--skip <n>` | Skip the N most recent sessions (useful when running as sub-agent) |
| `--session-id <id>` | Specific session ID to read |
| Option | Description |
| ------------------- | ------------------------------------------------------------------------------------------------------ |
| `--max-entries <n>` | Maximum entries to return (default: 200) |
| `--skip <n>` | Skip the N most recent top-level sessions (sub-agent sessions always excluded) |
| `--session-id <id>` | Specific session ID to read |
| `--root` | Resolve to the top-level (root) session — with `--session-id`, walks up from a sub-agent child session |

## Examples

Expand Down Expand Up @@ -97,3 +100,9 @@ Read the parent session (skip the sub-agent's own session):
```bash
archgate session-context claude-code --skip 1
```

Resolve an opencode sub-agent child session to its top-level ancestor:

```bash
archgate session-context opencode --session-id ses_child123 --root
```
7 changes: 6 additions & 1 deletion src/commands/session-context/opencode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const maxEntriesOption = new Option(

const skipOption = new Option(
"--skip <n>",
"skip the N most recent sessions (useful when running as a sub-agent)"
"skip the N most recent top-level sessions (sub-agent sessions are always excluded)"
)
.argParser((val) => Math.trunc(Number(val)))
.default(0);
Expand All @@ -28,13 +28,18 @@ export function registerOpencodeSessionContextCommand(parent: Command) {
.addOption(maxEntriesOption)
.addOption(skipOption)
.option("--session-id <id>", "Specific session ID to read")
.option(
"--root",
"resolve to the top-level (root) session — with --session-id, walks up from a sub-agent child session"
)
.action(async (opts) => {
try {
const projectRoot = findProjectRoot();
const result = await readOpencodeSession(projectRoot, {
maxEntries: opts.maxEntries,
skip: opts.skip,
sessionId: opts.sessionId,
root: opts.root,
});

if (!result.ok) {
Expand Down
Loading
Loading