fix(onboard): resolve Tests-lane failures for onboard workflow
- runtime-launcher-parity: recognize workflows that delegate gsd_run to references/gsd-run-resolver.md (onboard.md) and exempt them from the inline-preamble checks; add a compensating byte-equality guard (B2) asserting the reference bash block matches _runtime-launcher.snippet.sh. - onboard.md: document the TEXT_MODE plain-text/numbered-list fallback for AskUserQuestion on non-Claude runtimes (fixes ask-user-questions-fallback, #2012). - Regenerate golden-install-parity fixtures, docs/INVENTORY-MANIFEST.json (add gsd-run-resolver.md + onboard-projection.cjs), and tests/workflow-size-baseline.json. Co-authored-by: Codesmith <codesmith-bot@users.noreply.github.com>
This commit is contained in:
@@ -33,7 +33,7 @@ Parse JSON fields from `INIT`:
|
||||
- `commit_docs`, `text_mode`, `has_git`, `git_worktree_root`, `in_nested_subdir`
|
||||
|
||||
Set:
|
||||
- `TEXT_MODE=true` if `--text` is present or `text_mode` is true.
|
||||
- `TEXT_MODE=true` if `--text` is present or `text_mode` is true. When `TEXT_MODE` is active, replace every `AskUserQuestion` call below with a plain-text numbered list and ask the user to type their choice number — required for non-Claude runtimes (OpenAI Codex, Gemini CLI, etc.) where `AskUserQuestion` is not available.
|
||||
- `ONBOARDING_ROOT={git_worktree_root || _GSD_RUNTIME_ROOT}`.
|
||||
|
||||
If `has_git` and `in_nested_subdir` are true, warn that onboarding artifacts belong to the outer worktree at `git_worktree_root`. Do not run `git init`.
|
||||
|
||||
@@ -136,6 +136,22 @@ function collectAgentFiles() {
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* A workflow/agent file "delegates to the shared resolver" when it pulls the
|
||||
* canonical gsd_run preamble in from gsd-core/references/gsd-run-resolver.md via
|
||||
* an @-include instead of inlining the snippet (see onboard.md / issue #1990).
|
||||
*
|
||||
* Such files are exempt from the inline-preamble parity checks (B / G / H and the
|
||||
* runtime-home propagation checks): they intentionally do NOT inline the preamble
|
||||
* — onboard-command.test.cjs even asserts the absence of the inline form. Their
|
||||
* resolver correctness is guaranteed transitively by:
|
||||
* (1) onboard-command.test.cjs asserting the @-include is present, and
|
||||
* (2) the "resolver reference stays byte-equal to the snippet" guard (B2) below.
|
||||
*/
|
||||
function delegatesToResolverReference(content) {
|
||||
return content.includes('references/gsd-run-resolver.md');
|
||||
}
|
||||
|
||||
describe('runtime-launcher-parity (#373)', () => {
|
||||
// ─── (A) No retired GSD_SDK token ────────────────────────────────────────
|
||||
test('(A) no GSD_SDK token in any workflow .md file', () => {
|
||||
@@ -170,6 +186,9 @@ describe('runtime-launcher-parity (#373)', () => {
|
||||
for (const f of files) {
|
||||
const rel = path.relative(WORKFLOWS_DIR, f);
|
||||
const content = fs.readFileSync(f, 'utf8');
|
||||
// Files that delegate to the shared resolver reference (@-include) do not
|
||||
// inline the preamble — exempt them (see delegatesToResolverReference / (B2)).
|
||||
if (delegatesToResolverReference(content)) continue;
|
||||
const blocks = extractShellBlocks(content);
|
||||
|
||||
// Collect all block lines in document order for flat analysis
|
||||
@@ -226,6 +245,30 @@ describe('runtime-launcher-parity (#373)', () => {
|
||||
);
|
||||
});
|
||||
|
||||
// ─── (B2) Shared resolver reference stays byte-equal to the snippet ───────
|
||||
// Workflows may delegate to gsd-core/references/gsd-run-resolver.md instead of
|
||||
// inlining the preamble (see delegatesToResolverReference). That delegation is
|
||||
// only safe if the reference's bash block is byte-equal to the canonical
|
||||
// snippet — otherwise a delegating workflow (e.g. onboard.md) would silently
|
||||
// ship a drifted resolver. This guard replaces the inline-preamble checks for
|
||||
// those files.
|
||||
test('(B2) references/gsd-run-resolver.md preamble is byte-equal to the canonical snippet', () => {
|
||||
const preambleStr = expectedPreamble().join('\n');
|
||||
const refPath = path.join(__dirname, '..', 'gsd-core', 'references', 'gsd-run-resolver.md');
|
||||
const refContent = fs.readFileSync(refPath, 'utf8');
|
||||
const refPreamble = extractShellBlocks(refContent)
|
||||
.map((b) => b.lines.join('\n'))
|
||||
.join('\n')
|
||||
.trim();
|
||||
assert.equal(
|
||||
refPreamble,
|
||||
preambleStr,
|
||||
'gsd-core/references/gsd-run-resolver.md must contain the canonical gsd_run preamble ' +
|
||||
'byte-equal to _runtime-launcher.snippet.sh. Re-copy the snippet into the reference so ' +
|
||||
'workflows that delegate to it via @-include ship the current resolver.',
|
||||
);
|
||||
});
|
||||
|
||||
// ─── (C) Space-safe behavioral test ──────────────────────────────────────
|
||||
test('(C) gsd_run works with a RUNTIME_DIR path containing spaces', () => {
|
||||
// Create temp dir whose path contains a space
|
||||
@@ -402,6 +445,7 @@ describe('runtime-launcher-parity (#373)', () => {
|
||||
const content = fs.readFileSync(f, 'utf8');
|
||||
const blocks = extractShellBlocks(content);
|
||||
const allBlockLines = blocks.flatMap((b) => b.lines);
|
||||
if (delegatesToResolverReference(content)) continue;
|
||||
const fileHasGsdRun = allBlockLines.some((l) => /\bgsd_run\b/.test(l));
|
||||
if (!fileHasGsdRun) continue;
|
||||
const allContent = allBlockLines.join('\n');
|
||||
@@ -433,6 +477,7 @@ describe('runtime-launcher-parity (#373)', () => {
|
||||
const content = fs.readFileSync(f, 'utf8');
|
||||
const blocks = extractShellBlocks(content);
|
||||
const allBlockLines = blocks.flatMap((b) => b.lines);
|
||||
if (delegatesToResolverReference(content)) continue;
|
||||
const fileHasGsdRun = allBlockLines.some((l) => /\bgsd_run\b/.test(l));
|
||||
if (!fileHasGsdRun) continue;
|
||||
if (!allBlockLines.join('\n').includes(CODEX_HOME_PROBE)) {
|
||||
@@ -1346,6 +1391,7 @@ describe('bug-891: non-Claude runtime home fallback arms', () => {
|
||||
const content = fs.readFileSync(f, 'utf8');
|
||||
const blocks = extractShellBlocks(content);
|
||||
const allBlockLines = blocks.flatMap((b) => b.lines);
|
||||
if (delegatesToResolverReference(content)) continue;
|
||||
const fileHasGsdRun = allBlockLines.some((l) => /\bgsd_run\b/.test(l));
|
||||
if (!fileHasGsdRun) continue;
|
||||
const allContent = allBlockLines.join('\n');
|
||||
|
||||
Reference in New Issue
Block a user