Skip to content
Closed
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
8 changes: 4 additions & 4 deletions scripts/validate-gh-aw-cast.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,7 @@ function committedRegistry(root, errors) {
}
}

function parseRegistry(root, errors) {
function parseRegistry(root, errors, gitRoot = root) {
let registryRaw;
let historyRaw;
try {
Expand All @@ -543,7 +543,7 @@ function parseRegistry(root, errors) {
}
const registry = parseCastingPair(registryRaw, historyRaw, 'registry', errors);
if (!registry) return [];
const base = committedRegistry(root, errors);
const base = committedRegistry(gitRoot, errors);
if (base) {
const baseRevision = base.schema === 'squad-agent-provenance/v1' ? base.revision : 0;
if (registry.revision <= baseRevision) {
Expand Down Expand Up @@ -631,7 +631,7 @@ function validateCapabilities(coordinator, active, routingRows, errors) {
}
}

export function validateCastTree({ root, payloadPath }) {
export function validateCastTree({ root, payloadPath, gitRoot = root }) {
const errors = [];
let payloadValue;
try {
Expand Down Expand Up @@ -660,7 +660,7 @@ export function validateCastTree({ root, payloadPath }) {
if (!payload.includes(required)) errors.push(`payload: missing required path ${required}`);
}

const active = parseRegistry(root, errors);
const active = parseRegistry(root, errors, gitRoot);
const activeNames = new Set(active.map(({ name }) => name));
const activeCharters = active.map(({ id }) => `.squad/agents/${id}/charter.md`);
const expectedPayload = new Set([...CORE_PAYLOAD, ...activeCharters, ...REQUIRED_BUILTIN_CHARTERS]);
Expand Down
22 changes: 22 additions & 0 deletions test/gh-aw-bootstrap-workflow.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
findBootstrapResearchArtifacts,
isBootstrapResearchSeed,
reconstructBootstrapPayload,
validateBootstrapPayload,
} from '../workflows/shared/squad-bootstrap-validator.mjs';

const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..');
Expand Down Expand Up @@ -612,6 +613,27 @@ describe('automatic Squad bootstrap workflow', () => {
expect(resolvedResult.stdout).toBe('Squad bootstrap validation passed.\n');
});

it('validates an isolated candidate without .git against the checkout committed registry', () => {
const fixture = createFixture();
const candidate = mkdtempSync(join(tmpdir(), 'gh-aw-bootstrap-candidate-'));
workspaces.push(candidate);
cpSync(fixture.root, candidate, {
recursive: true,
filter: source => !/(^|[\\/])\.git([\\/]|$)/.test(source.slice(fixture.root.length)),
});
expect(existsSync(join(candidate, '.git'))).toBe(false);
const options = {
root: candidate,
payloadPath: fixture.payloadPath,
repository: 'octo/example',
defaultBranch: 'main',
linkMode: 'placeholder',
};

expect(validateBootstrapPayload(options).join('\n')).toContain('registry base: committed HEAD is unavailable');
expect(validateBootstrapPayload({ ...options, gitRoot: fixture.root })).toEqual([]);
});

it('transports a shared payload larger than the old single-string limit byte-identically', () => {
const fixture = createFixture();
const targetBytes = 34_843;
Expand Down
6 changes: 3 additions & 3 deletions test/gh-aw-quality.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3961,8 +3961,8 @@ describe('gh-aw: canonical package integrity contract', () => {
expect(mutable).not.toContain(actionReference);
expect(createHash('sha256').update(normalizeCompiledLock(mutable, revisionA)).digest('hex'))
.toBe(sourceBinding === 'workflow'
? '8456d8129241269c107cdf4b16ae079e89a98ef944152df36f53ec0decf3f30d'
: 'bac4d8b90269d827fc9e626dd02c1b536bccde7105e9037971740054cda4c19b');
? '264c154a950ba0e414a7410aca2f9d64f6472796b48d395bda98a03e5e8551f5'
: '2482e11b6489da9c02efa25e9a1d64c99a736fe39e6e8bf75b7999709d07445e');
expect(() => validateCompilerActionPins(mutable)).toThrow(/invalid immutable action pin/);
writeFileSync(lockPath, mutable);
expect(verifyInstall(root).failures.join('\n'))
Expand Down Expand Up @@ -4016,7 +4016,7 @@ describe('gh-aw: canonical package integrity contract', () => {
compile();
const unpinned = readText(lockPath);
expect(createHash('sha256').update(normalizeCompiledLock(unpinned, revisionA)).digest('hex'))
.toBe('bac4d8b90269d827fc9e626dd02c1b536bccde7105e9037971740054cda4c19b');
.toBe('2482e11b6489da9c02efa25e9a1d64c99a736fe39e6e8bf75b7999709d07445e');
expect(verifyInstall(root).failures.join('\n')).toContain('Installed digest mismatch');

const seedPins = () => spawnSync(process.execPath, ['--input-type=module', '-e', seed!], {
Expand Down
5 changes: 3 additions & 2 deletions workflows/package/squad-bootstrap.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,8 @@ pre-agent-steps:
}
# BEGIN GENERATED RESOURCE DIGESTS
check_hash "$install_verifier" "40753edd5995c5f7ba058f57fbcc5aff0ccf3341c721b764fa0cf1dc70eba3f1"
check_hash "$cast_validator" "0988e04aeef316f4d7a0107c902bbbcf6538b8899b9fffba5f62150717967685"
check_hash "$bootstrap_validator" "4fc1bcc79b887bb4f2f78e7eef8693d5c1eaf817d8715ce3c92169934aa225b7"
check_hash "$cast_validator" "c6d0b92aac71dc6f6d5727cac418a323b0bc9c12047400faa12d96150d548ada"
check_hash "$bootstrap_validator" "6f2ff60104a238c7c171031e737fd8dcb57dd3eeffccbf8c0aeaad016d85ee4e"
# END GENERATED RESOURCE DIGESTS
node "$bootstrap_validator" \
--encode-payload "${GITHUB_WORKSPACE:?}/.github/workflows/squad-bootstrap-payload.json" \
Expand Down Expand Up @@ -316,6 +316,7 @@ safe-outputs:
writeFileSync(candidatePayloadPath, `${JSON.stringify(candidatePayload)}\n`);
const errors = validatorModule.validateBootstrapPayload({
root: candidate,
gitRoot: checkout,
payloadPath: candidatePayloadPath,
repository: context.repo.owner + '/' + context.repo.repo,
defaultBranch: process.env.SQUAD_BOOTSTRAP_DEFAULT_BRANCH,
Expand Down
2 changes: 1 addition & 1 deletion workflows/package/squad.md
Original file line number Diff line number Diff line change
Expand Up @@ -840,7 +840,7 @@ pre-agent-steps:
validator_script="$(cd "$(dirname "$validator_script")" && pwd -P)/$(basename "$validator_script")"

# BEGIN GENERATED RESOURCE DIGEST
validator_expected_sha256="0988e04aeef316f4d7a0107c902bbbcf6538b8899b9fffba5f62150717967685"
validator_expected_sha256="c6d0b92aac71dc6f6d5727cac418a323b0bc9c12047400faa12d96150d548ada"
# END GENERATED RESOURCE DIGEST
: > "$stderr_file"
validator_actual_sha256="$(
Expand Down
3 changes: 2 additions & 1 deletion workflows/shared/squad-bootstrap-validator.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,7 @@ export function createBootstrapResearchComment(issueBodyText, issueNumber) {

export function validateBootstrapPayload({
root,
gitRoot = root,
payloadPath,
repository,
defaultBranch,
Expand Down Expand Up @@ -588,7 +589,7 @@ export function validateBootstrapPayload({
try {
const castPayloadPath = join(tempDir, 'cast-paths.json');
writeFileSync(castPayloadPath, `${JSON.stringify(castPaths)}\n`);
errors.push(...validateCastTree({ root, payloadPath: castPayloadPath }));
errors.push(...validateCastTree({ root, gitRoot, payloadPath: castPayloadPath }));
} finally {
rmSync(tempDir, { recursive: true, force: true });
}
Expand Down
8 changes: 4 additions & 4 deletions workflows/shared/squad-cast-validator.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,7 @@ function committedRegistry(root, errors) {
}
}

function parseRegistry(root, errors) {
function parseRegistry(root, errors, gitRoot = root) {
let registryRaw;
let historyRaw;
try {
Expand All @@ -543,7 +543,7 @@ function parseRegistry(root, errors) {
}
const registry = parseCastingPair(registryRaw, historyRaw, 'registry', errors);
if (!registry) return [];
const base = committedRegistry(root, errors);
const base = committedRegistry(gitRoot, errors);
if (base) {
const baseRevision = base.schema === 'squad-agent-provenance/v1' ? base.revision : 0;
if (registry.revision <= baseRevision) {
Expand Down Expand Up @@ -631,7 +631,7 @@ function validateCapabilities(coordinator, active, routingRows, errors) {
}
}

export function validateCastTree({ root, payloadPath }) {
export function validateCastTree({ root, payloadPath, gitRoot = root }) {
const errors = [];
let payloadValue;
try {
Expand Down Expand Up @@ -660,7 +660,7 @@ export function validateCastTree({ root, payloadPath }) {
if (!payload.includes(required)) errors.push(`payload: missing required path ${required}`);
}

const active = parseRegistry(root, errors);
const active = parseRegistry(root, errors, gitRoot);
const activeNames = new Set(active.map(({ name }) => name));
const activeCharters = active.map(({ id }) => `.squad/agents/${id}/charter.md`);
const expectedPayload = new Set([...CORE_PAYLOAD, ...activeCharters, ...REQUIRED_BUILTIN_CHARTERS]);
Expand Down
5 changes: 3 additions & 2 deletions workflows/squad-bootstrap.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,8 @@ pre-agent-steps:
}
# BEGIN GENERATED RESOURCE DIGESTS
check_hash "$install_verifier" "40753edd5995c5f7ba058f57fbcc5aff0ccf3341c721b764fa0cf1dc70eba3f1"
check_hash "$cast_validator" "0988e04aeef316f4d7a0107c902bbbcf6538b8899b9fffba5f62150717967685"
check_hash "$bootstrap_validator" "4fc1bcc79b887bb4f2f78e7eef8693d5c1eaf817d8715ce3c92169934aa225b7"
check_hash "$cast_validator" "c6d0b92aac71dc6f6d5727cac418a323b0bc9c12047400faa12d96150d548ada"
check_hash "$bootstrap_validator" "6f2ff60104a238c7c171031e737fd8dcb57dd3eeffccbf8c0aeaad016d85ee4e"
# END GENERATED RESOURCE DIGESTS
node "$bootstrap_validator" \
--encode-payload "${GITHUB_WORKSPACE:?}/.github/workflows/squad-bootstrap-payload.json" \
Expand Down Expand Up @@ -307,6 +307,7 @@ safe-outputs:
writeFileSync(candidatePayloadPath, `${JSON.stringify(candidatePayload)}\n`);
const errors = validatorModule.validateBootstrapPayload({
root: candidate,
gitRoot: checkout,
payloadPath: candidatePayloadPath,
repository: context.repo.owner + '/' + context.repo.repo,
defaultBranch: process.env.SQUAD_BOOTSTRAP_DEFAULT_BRANCH,
Expand Down
16 changes: 8 additions & 8 deletions workflows/squad-workflows.manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
"source": "workflows/package/squad.md",
"destination": ".github/workflows/squad.md",
"lock": ".github/workflows/squad.lock.yml",
"source_sha256": "0f292c576983ac99dace0661e34f900ddd91fcd50f28ff6726eff78704e283f2",
"lock_sha256": "32df53558611b35f809ea40a0de0b1b33e4f4dda955400b5387e77f96cb25277",
"package_lock_sha256": "a3336602334921327ca585f2321f84547ac2fde94f22178e25dcb029dd1370e6"
"source_sha256": "f86eb83a75c6de63edf520bf21ca2b50fcb9c6e7c5a60ecbd92a527a108a19af",
"lock_sha256": "cecc8fc0903d7de78c8c62756439722d9a347c8c0af1da317d26a5fd4708e929",
"package_lock_sha256": "4da03e3363714608f1a4901e49dee75ae02238c273a0bae15603aa280e4e347c"
},
{
"name": "squad-implement-worker",
Expand Down Expand Up @@ -68,9 +68,9 @@
"source": "workflows/package/squad-bootstrap.md",
"destination": ".github/workflows/squad-bootstrap.md",
"lock": ".github/workflows/squad-bootstrap.lock.yml",
"source_sha256": "ca2981acbdee8ce1d4ce705b9132e3777ceb63574dd884d6c75af8a8dfe16240",
"lock_sha256": "fd1562548a1aace9c57bdf315266da413575ea07da1d4b64c4f6446afc6aefc5",
"package_lock_sha256": "8aa7f287d51079746d997e5c5f17e5807efd1dd53de1c403982fcd10de23dfc0"
"source_sha256": "be73bf3c95214de5dd4702405715d0118d8d23aebfd2d1a8822d5358e8afdf68",
"lock_sha256": "147d85f07eeb02cfde1222f46bdc1510cd1f2f1539d1407ab47b5d17484bb19f",
"package_lock_sha256": "95e403d96fd094def920f913e114a560d6bc6ef367797f5cb529ab757897d4de"
},
{
"name": "squad-command-router",
Expand Down Expand Up @@ -113,15 +113,15 @@
"package_destination": ".github/workflows/shared/squad-cast-validator.mjs",
"destination": ".github/workflows/shared/squad-cast-validator.mjs",
"ownership": "manifest",
"sha256": "0988e04aeef316f4d7a0107c902bbbcf6538b8899b9fffba5f62150717967685"
"sha256": "c6d0b92aac71dc6f6d5727cac418a323b0bc9c12047400faa12d96150d548ada"
},
{
"path": "shared/squad-bootstrap-validator.mjs",
"source": "workflows/shared/squad-bootstrap-validator.mjs",
"package_destination": ".github/workflows/shared/squad-bootstrap-validator.mjs",
"destination": ".github/workflows/shared/squad-bootstrap-validator.mjs",
"ownership": "manifest",
"sha256": "4fc1bcc79b887bb4f2f78e7eef8693d5c1eaf817d8715ce3c92169934aa225b7"
"sha256": "6f2ff60104a238c7c171031e737fd8dcb57dd3eeffccbf8c0aeaad016d85ee4e"
},
{
"path": "shared/squad-improvement-gate.mjs",
Expand Down
2 changes: 1 addition & 1 deletion workflows/squad.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ pre-agent-steps:
validator_script="$(cd "$(dirname "$validator_script")" && pwd -P)/$(basename "$validator_script")"

# BEGIN GENERATED RESOURCE DIGEST
validator_expected_sha256="0988e04aeef316f4d7a0107c902bbbcf6538b8899b9fffba5f62150717967685"
validator_expected_sha256="c6d0b92aac71dc6f6d5727cac418a323b0bc9c12047400faa12d96150d548ada"
# END GENERATED RESOURCE DIGEST
: > "$stderr_file"
validator_actual_sha256="$(
Expand Down
Loading