mirror of
https://github.com/garrytan/gstack.git
synced 2026-11-01 06:24:41 +01:00
W4: transcript consent prose in /setup-gbrain, /sync-gbrain and memory.md
The Step 7.5 gate is rewritten as a consent question (manual merge of s09 H5, with H1b and H6): it checks gstack-config has, asks once with A) recent, B) all history, E) never, names Claude Code and Codex sessions from every repo-policy-allowed project and the destination brain, stores the mode value (never the letter), asks yes/no when no transcripts exist, never asks spawned or headless sessions, and drops the silent no-question bulk paths and the false skill-start-hook claim (s09 H5c). Path 4 no longer stores off on the user's behalf. /sync-gbrain gains Step 1.6 (ask when the key is absent or holds a legacy value). Step 10 and the sync verdict show the mode. setup-gbrain/memory.md gains #transcripts (values, sources, destination, override precedence, one-time restage, held staged pages, already-ingested pages stay). W7a: setup-gbrain-bin-invocation-paths drops the silent-bulk and preamble-hook pins (that prose is gone) for negative checks (no pre-answer --bulk, no skill-start claim), loosens the gstack-config pin (t06 #18) to the command without <choice>, and adds the DX 'gated on has' order check for both skills.
This commit is contained in:
1 parent
26c6bf263f
commit
67bd3d6267
6 files changed
+220
-69
No files matched your search
@@ -397,14 +397,15 @@ the prereq is fixed.
|
||||
|
||||
---
|
||||
|
||||
## Step 7.5: Transcript & memory ingest gate
|
||||
## Step 7.5: Transcript ingest consent
|
||||
|
||||
**SKIP entirely on Path 4 (Remote MCP).** Transcript ingest shells out to
|
||||
the local `gbrain` CLI which Path 4 doesn't install. Remote-mode users
|
||||
rely on the brain server's own ingest cadence — if your brain admin wants
|
||||
this machine's transcripts indexed, they pull from your `gstack-artifacts-$USER`
|
||||
repo (set up in Step 7) on whatever schedule they prefer. Set
|
||||
`gstack-config set transcript_ingest_mode off` and continue to Step 8.
|
||||
repo (set up in Step 7) on whatever schedule they prefer. Do not store a
|
||||
transcript mode for the user here; transcripts stay skipped until they choose
|
||||
(`/sync-gbrain` asks). Continue to Step 8.
|
||||
|
||||
For Paths 1, 2a, 2b, 3, run the ingest gate:
|
||||
|
||||
@@ -541,7 +542,7 @@ state, repairs only what's missing, and reports here.
|
||||
```bash
|
||||
eval "$(~/.claude/skills/gstack/bin/gstack-paths)"; : "${GSTACK_STATE_ROOT:?gstack-paths failed; reinstall with ./setup or /gstack-upgrade}"
|
||||
~/.claude/skills/gstack/bin/gstack-gbrain-detect 2>/dev/null || true
|
||||
~/.claude/skills/gstack/bin/gstack-config get transcript_ingest_mode 2>/dev/null || echo "off"
|
||||
~/.claude/skills/gstack/bin/gstack-config has transcript_ingest_mode && echo "transcript_ingest_mode: $(~/.claude/skills/gstack/bin/gstack-config get transcript_ingest_mode)" || echo "transcript_ingest_mode: not set"
|
||||
~/.claude/skills/gstack/bin/gstack-config get artifacts_sync_mode 2>/dev/null || echo "off"
|
||||
[ -f "$GSTACK_STATE_ROOT"/.gbrain-sync-state.json ] && cat "$GSTACK_STATE_ROOT"/.gbrain-sync-state.json || echo "{}"
|
||||
```
|
||||
@@ -561,7 +562,7 @@ gbrain status: GREEN (mode: remote-http)
|
||||
Repo policy ..... OK {read-write|read-only|deny}
|
||||
Artifacts repo .. OK {gstack_artifacts_remote URL}
|
||||
Artifacts sync .. OK {artifacts_sync_mode}
|
||||
Transcripts ..... OK route to artifacts repo → remote brain
|
||||
Transcripts ..... OK {recent|all}: route to artifacts repo → remote brain | INFO {off|not set}: skipped
|
||||
Code search ..... {OK local-pglite (~/.gbrain/pglite) | N/A declined at Step 4d}
|
||||
CLAUDE.md ....... OK
|
||||
Smoke test ...... INFO printed for post-restart manual verification
|
||||
@@ -592,13 +593,16 @@ gbrain status: GREEN (mode: local-stdio)
|
||||
Repo policy ..... OK <read-write|read-only|deny>
|
||||
Code import ..... OK <last_imported_head>
|
||||
Artifacts sync .. OK <artifacts_sync_mode> to <remote>
|
||||
Transcripts ..... OK <N> sessions, last ingest <when>
|
||||
Transcripts ..... OK <recent|all>: <N> sessions, last ingest <when> | INFO <off|not set>: skipped
|
||||
CLAUDE.md ....... OK
|
||||
Smoke test ...... OK put → search round-trip
|
||||
|
||||
Run `/setup-gbrain` again any time gbrain feels off; it's safe and idempotent.
|
||||
```
|
||||
|
||||
A `not set` transcript mode is not a failure: transcripts stay skipped until
|
||||
the user chooses, and `/sync-gbrain` asks.
|
||||
|
||||
If any row is YELLOW or RED, the verdict line says so and the failing rows
|
||||
surface a one-line "next action" (e.g.,
|
||||
`Engine .......... ERR PGLite corrupt — re-import from a clone of your brain remote with \`gbrain import\``).
|
||||
|
||||
+60
-4
@@ -1,9 +1,9 @@
|
||||
# gstack memory ingest — what it does, what stays local, what you can do with it
|
||||
|
||||
This is the user-facing reference for the V1 transcript + memory ingest
|
||||
feature in `/setup-gbrain`. If you ran `/setup-gbrain` and it asked
|
||||
"Ingest THIS repo's transcripts into gbrain?", this doc explains what
|
||||
happens after you say yes.
|
||||
This is the user-facing reference for the transcript + memory ingest
|
||||
feature in `/setup-gbrain` and `/sync-gbrain`. If either asked whether to
|
||||
ingest your coding-agent sessions into gbrain, this doc explains what each
|
||||
answer does.
|
||||
|
||||
## What gets ingested
|
||||
|
||||
@@ -20,6 +20,62 @@ happens after you say yes.
|
||||
| Retros | `retro` | `~/.gstack/projects/<slug>/retros/*.md` | Medium |
|
||||
| Builder profile | `builder-profile-entry` | `~/.gstack/builder-profile.jsonl` | Low |
|
||||
|
||||
## Transcripts
|
||||
|
||||
Curated memory (learnings, timeline, plans, designs, retros, eureka, builder
|
||||
profile) syncs on every `/sync-gbrain`. Session transcripts sync only after
|
||||
you choose to share them. The choice is the `transcript_ingest_mode` config
|
||||
key:
|
||||
|
||||
| Value | What `/sync-gbrain` ingests |
|
||||
|---|---|
|
||||
| `recent` | Sessions from the last 90 days |
|
||||
| `all` | All history (`--full` walks every session file) |
|
||||
| `off` | No transcripts; other memory still syncs |
|
||||
|
||||
Both sources are covered: Claude Code sessions (`~/.claude/projects/`) and
|
||||
Codex sessions (`~/.codex/sessions/`), from every project on this machine
|
||||
that your per-remote trust policy allows, not only the current repo. Pages go
|
||||
to your brain: the local engine (PGLite or Supabase) in local-stdio mode, or
|
||||
the artifacts repo the remote brain pulls from in remote-http mode.
|
||||
|
||||
Set or change it:
|
||||
|
||||
```bash
|
||||
gstack-config set transcript_ingest_mode recent # or all, or off
|
||||
gstack-config has transcript_ingest_mode && gstack-config get transcript_ingest_mode
|
||||
```
|
||||
|
||||
`gstack-config set` rejects any other value and keeps the stored one.
|
||||
|
||||
**Not set.** Until you choose, transcripts are skipped. Each sync prints one
|
||||
line saying so, even with `--quiet`, and the next interactive `/sync-gbrain`
|
||||
asks once. Older values from previous gate versions (`A`-`E`, `incremental`)
|
||||
also count as not chosen and get the question again. A stored `off` prints
|
||||
`transcripts off (your choice)` without `--quiet` and is never asked again.
|
||||
|
||||
**One-run override.** A `--sources` list (or `GSTACK_MEMORY_INGEST_SOURCES`)
|
||||
that names `transcript` ingests transcripts for that run whatever the mode;
|
||||
the sync still prints the mode notice. `--sources all`, an empty list, or a
|
||||
list with no valid types does not override.
|
||||
|
||||
```bash
|
||||
bun run bin/gstack-gbrain-sync.ts --incremental --sources transcript
|
||||
```
|
||||
|
||||
**Interrupted imports.** If a sync was interrupted mid-import and your
|
||||
transcript choice changed before the next run, the next sync restages memory
|
||||
from scratch once instead of resuming, and prints a line saying so.
|
||||
|
||||
**Staged pages wait.** Transcript pages already staged under
|
||||
`~/.gstack/transcripts/` (remote-http mode) stay on disk and are not pushed
|
||||
by `gstack-brain-sync` until the mode is `recent` or `all`. Other artifacts
|
||||
keep pushing.
|
||||
|
||||
**Already-ingested transcripts stay.** Switching to `off` stops new ingests;
|
||||
it does not remove pages already in the brain. Delete them there (see
|
||||
"Delete a page" below).
|
||||
|
||||
## What stays local
|
||||
|
||||
- **State files** (`~/.gstack/.gbrain-sync-state.json`,
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
{
|
||||
"id": "transcript-gate",
|
||||
"file": "transcript-gate.md",
|
||||
"title": "Step 7.5: transcript & memory ingest gate (probe, thresholds, ingest AskUserQuestion)",
|
||||
"title": "Step 7.5: transcript ingest consent (has-check, probe, recent/all/off AskUserQuestion)",
|
||||
"trigger": "running the Step 7.5 transcript & memory ingest gate on Paths 1, 2a, 2b, or 3 (Path 4 skips this section entirely — see the skeleton's skip note)"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,64 +1,90 @@
|
||||
After memory sync is wired (Step 7) but before persisting the CLAUDE.md
|
||||
config (Step 8), offer to bring this Mac's coding-agent transcripts +
|
||||
curated `~/.gstack/` artifacts into gbrain so the retrieval surface
|
||||
(per-skill manifests, salience block) has data to surface.
|
||||
config (Step 8), ask whether this machine's coding-agent session
|
||||
transcripts may go into gbrain. Curated `~/.gstack/` artifacts (learnings,
|
||||
timeline, plans, designs, retros) sync whatever the answer; this question
|
||||
covers transcripts only. Transcripts are ingested only after the user picks
|
||||
`recent` or `all`.
|
||||
|
||||
Run the probe to size the operation:
|
||||
Check whether the user already chose. The gate keys on `has`, because `get`
|
||||
prints the `off` default for a key that was never set:
|
||||
```bash
|
||||
bun run ~/.claude/skills/gstack/bin/gstack-memory-ingest.ts --probe
|
||||
_TIM=$(~/.claude/skills/gstack/bin/gstack-config get transcript_ingest_mode 2>/dev/null || true)
|
||||
if ~/.claude/skills/gstack/bin/gstack-config has transcript_ingest_mode; then
|
||||
case "$(printf '%s' "$_TIM" | tr -d '[:space:]' | tr '[:upper:]' '[:lower:]')" in
|
||||
recent|all|off) echo "TRANSCRIPT_MODE: $_TIM" ;;
|
||||
*) echo "TRANSCRIPT_MODE: ask (stored value '$_TIM' is from an older version)" ;;
|
||||
esac
|
||||
else
|
||||
echo "TRANSCRIPT_MODE: ask (not set)"
|
||||
fi
|
||||
```
|
||||
|
||||
Read the output. If `Total files in window: 0`, skip — there's nothing
|
||||
to ingest. Set `gstack-config set transcript_ingest_mode incremental`
|
||||
silently and continue to Step 8.
|
||||
- `TRANSCRIPT_MODE: recent`, `all` or `off`: the user already chose. Do not
|
||||
ask again; continue to Step 8.
|
||||
- `TRANSCRIPT_MODE: ask`: ask once, below. With `SESSION_KIND: spawned` or
|
||||
`headless`, do not ask and do not store a value. Consent is never
|
||||
auto-chosen; leave the key unset (transcripts stay skipped) and report
|
||||
that the next interactive `/sync-gbrain` will ask.
|
||||
|
||||
If `New (never ingested)` is < 200 AND total bytes are < 100MB: silent
|
||||
bulk via `bun run ~/.claude/skills/gstack/bin/gstack-memory-ingest.ts --bulk --quiet`. Set
|
||||
`transcript_ingest_mode=incremental` and continue.
|
||||
Size the question with two probes. `--sources transcript` makes the probe
|
||||
count transcripts even though none are consented yet:
|
||||
```bash
|
||||
bun run ~/.claude/skills/gstack/bin/gstack-memory-ingest.ts --probe --sources transcript
|
||||
bun run ~/.claude/skills/gstack/bin/gstack-memory-ingest.ts --probe --sources transcript --all-history
|
||||
```
|
||||
Read `Total files in window`, `Total bytes` and the estimate from each.
|
||||
|
||||
Otherwise (the "many transcripts on disk" path): AskUserQuestion with
|
||||
the exact counts AND the value promise. Default scope is **current repo
|
||||
only, last 90 days**:
|
||||
**No transcripts found** (both probes report 0): ask yes/no instead:
|
||||
|
||||
> "Found <N_repo> transcripts in THIS repo (<repo-slug>) over the last
|
||||
> 90 days, plus <N_other> across other repos on this machine (<bytes>
|
||||
> total if all ingested). Ingest THIS repo's transcripts into gbrain?
|
||||
> "Ingest coding-agent sessions as they appear?"
|
||||
|
||||
Yes stores `recent`; No stores `off`.
|
||||
|
||||
**Otherwise**, AskUserQuestion with the counts. Name both session sources
|
||||
and the destination brain from Step 4: the user's Supabase brain (Paths 1,
|
||||
2a, 2b) or the local PGLite brain on this machine (Path 3).
|
||||
|
||||
> "Found <N_recent> Claude Code and Codex sessions from the last 90 days
|
||||
> (<N_all> in all history, <bytes>) across the projects on this machine
|
||||
> that your repo policy allows. Ingest them into your <Supabase | local
|
||||
> PGLite> brain?
|
||||
>
|
||||
> What you get after this: every gstack skill auto-loads recent salience
|
||||
> from your past sessions in this repo, so the agent finds your prior
|
||||
> work without you describing it. You can query 'what was I doing on
|
||||
> day X' and get a real answer. Per-session pages are searchable,
|
||||
> taggable, and deletable. Secret scanning runs before any push.
|
||||
> What you get: gstack skills load recent context from your past sessions,
|
||||
> so the agent finds your prior work without you describing it, and you
|
||||
> can ask 'what was I doing on day X'. Per-session pages are searchable,
|
||||
> taggable and deletable. Secret scanning runs before any push.
|
||||
>
|
||||
> What stays the same: nothing leaves your machine unless gbrain sync
|
||||
> is enabled (Step 7). Per-repo trust policies still apply.
|
||||
> What stays the same: nothing leaves this machine unless brain sync is
|
||||
> enabled (Step 7). Per-repo trust policies still apply. The first full
|
||||
> sync can take a while on a large history (estimate: <est>); skills stay
|
||||
> usable while it runs.
|
||||
>
|
||||
> Multi-Mac note: if you HAVE enabled brain sync (Step 7), these
|
||||
> transcript pages will sync across your Macs. Caveat: deleting a
|
||||
> transcript page later removes it from gbrain but git history retains
|
||||
> it in prior commits. Use `gstack-transcript-prune` to delete in bulk;
|
||||
> use `git filter-repo` on the brain remote for hard-delete from
|
||||
> history."
|
||||
> Multi-machine note: with brain sync enabled, transcript pages sync across
|
||||
> your machines. Deleting a page later removes it from gbrain, but git
|
||||
> history keeps it in earlier commits. Use `gstack-transcript-prune` to
|
||||
> delete in bulk, and `git filter-repo` on the brain remote to remove it
|
||||
> from history."
|
||||
|
||||
Options:
|
||||
- A) Yes — this repo, last 90 days (recommended; ~est min)
|
||||
- B) Yes — this repo, ALL history
|
||||
- C) Yes — this repo + other repos on this machine
|
||||
- D) Skip historical, track new from now (`transcript_ingest_mode=incremental`)
|
||||
- E) Never ingest transcripts (`transcript_ingest_mode=off`)
|
||||
- A) Yes, last 90 days (`recent`)
|
||||
- B) Yes, all history (`all`)
|
||||
- E) No, never ingest transcripts (`off`)
|
||||
|
||||
After answer:
|
||||
Store the mode value, never the letter:
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-config set transcript_ingest_mode <recent|all|off>
|
||||
```
|
||||
|
||||
For `recent` or `all`, run the first sync now:
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-config set transcript_ingest_mode <choice>
|
||||
bun run ~/.claude/skills/gstack/bin/gstack-gbrain-sync.ts --full --no-brain-sync
|
||||
```
|
||||
(`--no-brain-sync` because Step 7 already wired that path; this just
|
||||
runs the code import + memory ingest stages. Brain-sync will run on the
|
||||
next preamble hook.)
|
||||
(`--no-brain-sync` because Step 7 already wired that path; this runs the
|
||||
code import and memory ingest stages, and `all` walks the full history.)
|
||||
For `off`, run nothing here; other memory still syncs on the next
|
||||
`/sync-gbrain`.
|
||||
|
||||
If A/D/E, ingest is incremental from this point on; preamble-boundary
|
||||
hook runs `bun run ~/.claude/skills/gstack/bin/gstack-gbrain-sync.ts --incremental --quiet` on every skill
|
||||
start (cheap mtime fast-path).
|
||||
New transcripts are ingested on the next `/sync-gbrain` run. Nothing at
|
||||
skill start ingests them.
|
||||
|
||||
Reference doc for users: `setup-gbrain/memory.md` (linked from CLAUDE.md
|
||||
Step 8).
|
||||
Reference doc for users: `setup-gbrain/memory.md#transcripts`.
|
||||
@@ -53,7 +53,7 @@ the skill itself, not a dispatcher binary):
|
||||
- `/sync-gbrain --code-only` — only run the code stage; skip memory + brain-sync
|
||||
- `/sync-gbrain --dry-run` — preview what would sync; no writes anywhere
|
||||
- `/sync-gbrain --no-memory` / `--no-brain-sync` — selectively skip stages
|
||||
- `/sync-gbrain --sources <types|all>` — memory types to ingest (env `GSTACK_MEMORY_INGEST_SOURCES`); by default, types a federated gstack source already indexes are skipped
|
||||
- `/sync-gbrain --sources <types|all>` — memory types to ingest (env `GSTACK_MEMORY_INGEST_SOURCES`); by default, types a federated gstack source already indexes are skipped, and transcripts are skipped unless `transcript_ingest_mode` is `recent` or `all` (a list naming `transcript` overrides that for one run)
|
||||
- `/sync-gbrain --quiet` — suppress per-stage output
|
||||
- `/sync-gbrain --refresh-cache` — force-rebuild brain-aware planning cache. Skips code + memory stages; routes to `gstack-brain-cache refresh --project <slug>`.
|
||||
- `/sync-gbrain --audit` — emit summary of gstack-owned pages per project + sensitive-content audit. Read-only.
|
||||
@@ -187,6 +187,61 @@ gets the actionable remediation message.
|
||||
|
||||
---
|
||||
|
||||
## Step 1.6: Transcript consent
|
||||
|
||||
Claude Code and Codex session transcripts are ingested only when
|
||||
`transcript_ingest_mode` is `recent` (last 90 days) or `all` (all history).
|
||||
Skip this step for `--code-only`, `--no-memory`, `--dry-run`,
|
||||
`--refresh-cache` and `--audit`. Otherwise check whether the user chose;
|
||||
`has` tells an absent key from the `off` default that `get` prints:
|
||||
|
||||
```bash
|
||||
_TIM=$(~/.claude/skills/gstack/bin/gstack-config get transcript_ingest_mode 2>/dev/null || true)
|
||||
if ~/.claude/skills/gstack/bin/gstack-config has transcript_ingest_mode; then
|
||||
case "$(printf '%s' "$_TIM" | tr -d '[:space:]' | tr '[:upper:]' '[:lower:]')" in
|
||||
recent|all|off) echo "TRANSCRIPT_MODE: $_TIM" ;;
|
||||
*) echo "TRANSCRIPT_MODE: ask (stored value '$_TIM' is from an older version)" ;;
|
||||
esac
|
||||
else
|
||||
echo "TRANSCRIPT_MODE: ask (not set)"
|
||||
fi
|
||||
```
|
||||
|
||||
`recent`, `all` or `off`: continue to Step 2 without asking. On `ask`, with
|
||||
`SESSION_KIND: spawned` or `headless`, do not ask and store nothing: the sync
|
||||
skips transcripts and prints how to choose. In an interactive session, ask
|
||||
once. Count first (`--sources transcript` counts sessions that are not
|
||||
consented yet):
|
||||
|
||||
```bash
|
||||
bun run ~/.claude/skills/gstack/bin/gstack-memory-ingest.ts --probe --sources transcript
|
||||
bun run ~/.claude/skills/gstack/bin/gstack-memory-ingest.ts --probe --sources transcript --all-history
|
||||
```
|
||||
|
||||
If both report `Total files in window: 0`, ask yes/no: "Ingest coding-agent
|
||||
sessions as they appear?" Yes stores `recent`, No stores `off`. Otherwise
|
||||
AskUserQuestion: name both sources (Claude Code and Codex sessions from every
|
||||
project on this machine that repo policy allows), the counts from the two
|
||||
probes, and the destination: the local brain (`gbrain_engine` from Step 1:
|
||||
PGLite or Supabase) or, in remote-http mode, the artifacts repo the remote
|
||||
brain pulls from. Say that a full sync of a large history can take a while
|
||||
and skills stay usable meanwhile. Options:
|
||||
|
||||
- A) Yes, last 90 days (`recent`)
|
||||
- B) Yes, all history (`all`)
|
||||
- E) No, never ingest transcripts (`off`)
|
||||
|
||||
Store the value, never the letter, then continue to Step 2:
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-config set transcript_ingest_mode <recent|all|off>
|
||||
```
|
||||
|
||||
Other memory types sync whatever the answer. Details:
|
||||
`setup-gbrain/memory.md#transcripts`.
|
||||
|
||||
---
|
||||
|
||||
## Step 2: Run the orchestrator
|
||||
|
||||
Pass user args to the orchestrator. Do not paraphrase them — pass through
|
||||
@@ -444,6 +499,7 @@ gbrain status: GREEN
|
||||
Call graph ...... OK <N> edges resolved (code-callers/callees live)
|
||||
~/.gstack source. OK <gstack-brain-{user}> (page_count=<N>) — managed by /setup-gbrain
|
||||
Memory sync ..... OK <artifacts_sync_mode>
|
||||
Transcripts ..... OK <recent|all> | INFO <off|not set>: skipped
|
||||
CLAUDE.md ....... OK ## GBrain Search Guidance present
|
||||
Last sync ....... OK <last_sync from state file>
|
||||
|
||||
|
||||
@@ -74,10 +74,8 @@ describe('setup-gbrain templates (skeleton + sections) — bin invocation paths'
|
||||
);
|
||||
});
|
||||
|
||||
test('the silent-bulk mention uses bun run + .ts (R2, transcript-gate section)', () => {
|
||||
expect(transcriptGate).toContain(
|
||||
'bun run ~/.claude/skills/gstack/bin/gstack-memory-ingest.ts --bulk --quiet'
|
||||
);
|
||||
test('the gate never bulk-ingests before the user answers (transcript-gate section)', () => {
|
||||
expect(transcriptGate).not.toMatch(/gstack-memory-ingest\.ts --bulk/);
|
||||
});
|
||||
|
||||
test('the post-answer full-sync step uses bun run + .ts (R3, transcript-gate section)', () => {
|
||||
@@ -86,19 +84,30 @@ describe('setup-gbrain templates (skeleton + sections) — bin invocation paths'
|
||||
);
|
||||
});
|
||||
|
||||
test('the preamble-hook incremental-sync mention uses bun run + .ts (R4, transcript-gate section)', () => {
|
||||
expect(transcriptGate).toContain(
|
||||
'bun run ~/.claude/skills/gstack/bin/gstack-gbrain-sync.ts --incremental --quiet'
|
||||
);
|
||||
test('no skill-start hook is claimed to ingest transcripts; /sync-gbrain is named (transcript-gate section)', () => {
|
||||
expect(transcriptGate).not.toMatch(/every skill\s+start/i);
|
||||
expect(transcriptGate).toContain('/sync-gbrain');
|
||||
});
|
||||
|
||||
test('the neighboring gstack-config line in the post-answer block is untouched (bash script, no extension)', () => {
|
||||
expect(transcriptGate).toContain(
|
||||
'~/.claude/skills/gstack/bin/gstack-config set transcript_ingest_mode <choice>'
|
||||
);
|
||||
test('the post-answer gstack-config line stores a mode value, not the answer letter (bash script, no extension)', () => {
|
||||
expect(transcriptGate).toContain('~/.claude/skills/gstack/bin/gstack-config set transcript_ingest_mode');
|
||||
expect(transcriptGate).not.toContain('transcript_ingest_mode <choice>');
|
||||
});
|
||||
});
|
||||
|
||||
describe('transcript consent question is gated on `gstack-config has`', () => {
|
||||
const syncTmpl = fs.readFileSync(path.join(ROOT, 'sync-gbrain', 'SKILL.md.tmpl'), 'utf-8');
|
||||
for (const [name, text] of [['setup-gbrain transcript gate', transcriptGate], ['sync-gbrain', syncTmpl]] as const) {
|
||||
test(`${name} checks presence with has before asking, and never asks spawned or headless sessions`, () => {
|
||||
const hasAt = text.indexOf('gstack-config has transcript_ingest_mode');
|
||||
expect(hasAt).toBeGreaterThanOrEqual(0);
|
||||
expect(text.indexOf('AskUserQuestion', hasAt)).toBeGreaterThan(hasAt);
|
||||
for (const v of ['recent', 'all', 'off']) expect(text).toContain(`\`${v}\``);
|
||||
expect(text).toMatch(/spawned[\s\S]{0,40}headless[\s\S]{0,80}do not ask/i);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('setup-gbrain/memory.md — bin invocation paths', () => {
|
||||
test('no bare gstack-memory-ingest invocation remains', () => {
|
||||
expect(memoryDoc).not.toMatch(bareMemoryIngest);
|
||||
|
||||
Reference in new issue
Block a user