From 7bfe46b78162bd56319dff8678ca9e4f1d99ffc1 Mon Sep 17 00:00:00 2001 From: garrytan Date: Tue, 6 Oct 2026 18:26:39 +0000 Subject: [PATCH] fix: spawned sessions never auto-grant consent or publish off the machine (#3016) Spawned sessions auto-choose the recommended option except for destructive or irreversible choices. Main already withholds the artifacts-sync consent prompt from spawned sessions; the remaining gap was any other prompt whose recommended option grants a consent or syncs data off the machine. Every spawned directive (skill-start's block, the escape sentence, the Conductor deny reason and the AUQ-error fallback) now names that as irreversible. A consent the user already gave interactively stays in force. Co-authored-by: ekson73 --- bin/gstack-skill-start | 2 +- hosts/claude/hooks/auq-error-fallback-hook.ts | 4 +-- hosts/claude/hooks/spawned-directive.ts | 10 +++++-- test/spawned-consent-rule.test.ts | 30 +++++++++++++++++++ 4 files changed, 41 insertions(+), 5 deletions(-) create mode 100644 test/spawned-consent-rule.test.ts diff --git a/bin/gstack-skill-start b/bin/gstack-skill-start index 5869d3641..a06c3066d 100755 --- a/bin/gstack-skill-start +++ b/bin/gstack-skill-start @@ -539,7 +539,7 @@ fi # end interactive-onboarding guard (kind != spawned) # actually says "auto-choose". if [ "$_SESSION_KIND" = "spawned" ]; then _emit_block spawned-session < { + test('every hook directive for a spawned session carries the consent rule', () => { + expect(SPAWNED_CONSENT_RULE).toContain('never auto-choose it'); + for (const text of [SPAWNED_ESCAPE_SENTENCE, CONDUCTOR_SPAWNED_DENY_REASON, directiveFor('spawned')]) { + expect(text).toContain(SPAWNED_CONSENT_RULE); + } + }); + + test("skill-start's spawned-session block names consent and off-machine publishing as exceptions", () => { + const start = fs.readFileSync(path.join(ROOT, 'bin', 'gstack-skill-start'), 'utf8'); + const block = start.slice(start.indexOf('_emit_block spawned-session'), start.indexOf('EOI', start.indexOf('_emit_block spawned-session'))); + expect(block).toContain('never grant a consent or choose an option that publishes or syncs data off this machine'); + }); +});