mirror of
https://github.com/garrytan/gstack.git
synced 2026-10-31 14:06:50 +01:00
eval(ship-docsync): git check-ignore is a declared read in the docs observation interface
Run 37166586458 slice 2 (dfaf154): ship-docsync-completion's parent ran
'git check-ignore -v .qa-state' to verify the prompt's claim that the
observer probe is Git-excluded. The read was outside the closed Git list,
so the run's DOC_PATH replacement was unprovable and failed. check-ignore
cannot write; it joins the list and the interface prose. Free regression
replays the captured command against the fixture and keeps composition and
redirects rejected.
This commit is contained in:
1 parent
a05a01ee2d
commit
1ffd38eb46
2 files changed
+19
-2
No files matched your search
@@ -45,6 +45,23 @@ test('captured parent tree read is accepted without granting the captured child
|
||||
expect(docsToolFailures(remote, fixture, [], true)).toEqual(['command outside declared docs observation interface']);
|
||||
});
|
||||
|
||||
// Run 37166586458 slice 2 (dfaf154): the parent verified the prompt's claim that
|
||||
// .qa-state/ is Git-excluded. check-ignore is a declared Git read; composition is not.
|
||||
test('captured check-ignore read is declared, executes without changing the repository', () => {
|
||||
const command = 'git check-ignore -v .qa-state';
|
||||
expect(docsNativeInterface(fixture)).toContain('ls-files, check-ignore, rev-parse');
|
||||
expect(docsCommandAllowed(command, fixture)).toBe(true);
|
||||
const before = repoSnapshot(fixture.repo);
|
||||
const result = spawnSync('bash', ['-c', command], { cwd: fixture.repo, encoding: 'utf8', timeout: 10000 });
|
||||
expect(result.status).toBe(0);
|
||||
expect(result.stdout).toContain('.qa-state');
|
||||
expect(docsToolFailures(nativeResult(command, result.stdout), fixture, [], true)).toEqual([]);
|
||||
expect(repoSnapshot(fixture.repo)).toEqual(before);
|
||||
for (const denied of ['git check-ignore -v .qa-state; ls', 'git check-ignore -v .qa-state > out.txt']) {
|
||||
expect(docsCommandAllowed(denied, fixture)).toBe(false);
|
||||
}
|
||||
});
|
||||
|
||||
test('permitted peel reads execute as single literal Bash arguments without changing the repository', () => {
|
||||
const before = repoSnapshot(fixture.repo);
|
||||
for (const revision of ['HEAD^{tree}', 'HEAD^{}', 'HEAD^{commit}', 'HEAD^{object}', 'HEAD@{0}']) {
|
||||
|
||||
@@ -190,7 +190,7 @@ Keep artifacts concise: update the invocation record in place with ids, counts,
|
||||
}
|
||||
|
||||
const DOCS_READ_COMMANDS = ['pwd', 'ls', 'cat', 'sha256sum', 'stat'];
|
||||
const DOCS_GIT_READS = ['status', 'diff', 'show', 'log', 'ls-files', 'rev-parse', 'merge-base', 'hash-object'];
|
||||
const DOCS_GIT_READS = ['status', 'diff', 'show', 'log', 'ls-files', 'check-ignore', 'rev-parse', 'merge-base', 'hash-object'];
|
||||
const DOCS_SAFE_GIT_CONFIG = /^(?:core\.pager=cat|core\.quotepath=(?:true|false|on|off)|color\.[a-z.]+=(?:true|false|never|always|auto))$/i;
|
||||
|
||||
/**
|
||||
@@ -268,7 +268,7 @@ function literalDocsCommandAllowed(text: string, fixture: ReturnType<typeof fixt
|
||||
|
||||
export function docsNativeInterface(fixture: Pick<ReturnType<typeof fixtureDocs>, 'home' | 'repo' | 'skills'>, scripts: string[] = [], transport = false, insert = false): string {
|
||||
const skills = fixture.skills.split(path.sep).join('/');
|
||||
return `Fixture observation interface (applies to parent and every child; include this interface in child prompts): Bash may execute only separate literal pwd, ls, cat, stat, sha256sum, Git read commands (status, diff, show, log, ls-files, rev-parse, merge-base, hash-object without -w, branch --show-current), the exact generated Preamble block with its spawned prefix, or literal installed gstack-skill-start/gstack-skill-end commands for document-release (start requires GSTACK_SESSION_KIND=spawned). No shell composition, custom interpreters, arbitrary scripts, inline eval or memory-mapped writes. The only additional scripts are ${scripts.length ? scripts.join(', ') : 'none'}.${insert ? ` To insert one saved private Markdown artifact into another (a saved section file into a report), Bash may also run the single literal command cat SOURCE.md >> TARGET.md with absolute paths under ${fixture.home}.` : ''} Read/Glob/Grep remain available; Read skill and section files with Read (offset/limit for ranges), because Bash output over 30KB becomes a preview that no permitted Bash command can page. Use Write/Edit for permitted docs and private JSON/Markdown artifacts under ${fixture.home}; do not rewrite installed skills, config, actor state or scripts. No effects outside the owned fixture. The owner preserves evidence and cleans up. Missing observer coverage blocks acceptance; the Linux kernel monitor covers syscall writes in the product tree, not hostile processes or arbitrary external destinations.
|
||||
return `Fixture observation interface (applies to parent and every child; include this interface in child prompts): Bash may execute only separate literal pwd, ls, cat, stat, sha256sum, Git read commands (status, diff, show, log, ls-files, check-ignore, rev-parse, merge-base, hash-object without -w, branch --show-current), the exact generated Preamble block with its spawned prefix, or literal installed gstack-skill-start/gstack-skill-end commands for document-release (start requires GSTACK_SESSION_KIND=spawned). No shell composition, custom interpreters, arbitrary scripts, inline eval or memory-mapped writes. The only additional scripts are ${scripts.length ? scripts.join(', ') : 'none'}.${insert ? ` To insert one saved private Markdown artifact into another (a saved section file into a report), Bash may also run the single literal command cat SOURCE.md >> TARGET.md with absolute paths under ${fixture.home}.` : ''} Read/Glob/Grep remain available; Read skill and section files with Read (offset/limit for ranges), because Bash output over 30KB becomes a preview that no permitted Bash command can page. Use Write/Edit for permitted docs and private JSON/Markdown artifacts under ${fixture.home}; do not rewrite installed skills, config, actor state or scripts. No effects outside the owned fixture. The owner preserves evidence and cleans up. Missing observer coverage blocks acceptance; the Linux kernel monitor covers syscall writes in the product tree, not hostile processes or arbitrary external destinations.
|
||||
|
||||
The working directory for parent and child Bash calls is already ${fixture.repo}. Run Git reads directly, for example: git status, git diff --cached, git merge-base main HEAD, git rev-parse HEAD. Do not use Git global options such as -C, -c, --git-dir or --work-tree, and do not prepend cd or another shell wrapper. The literal git subcommand must immediately follow git; an absolute owned repository path does not make git -C an allowed command.
|
||||
|
||||
|
||||
Reference in new issue
Block a user