Skip to content
Draft
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
4 changes: 4 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ just dev

This command runs local D1 migration first, then starts the driver build, API Worker, and web app.

`just dev`, `just build`, and `just check` fail fast when `apps/driver` is not initialized or its checked-out commit differs from the gitlink recorded by the main repository. Run `git submodule update --init --checkout apps/driver` to restore the pinned Driver version. The guard never updates the submodule automatically, so intentional Driver work remains explicit and reviewable.

`just setup` also enables `submodule.recurse` in the current checkout so later Git operations keep submodule state visible and synchronized where Git supports recursive behavior. The fail-fast guard remains authoritative because local Git configuration can be changed or bypassed.

Default local URLs:

- Web: `http://localhost:5173`
Expand Down
10 changes: 8 additions & 2 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ default:

# Prepare a new checkout for local development.
setup:
git submodule update --init
git config submodule.recurse true
git submodule update --init --recursive --checkout
just driver-submodule-check
bun install --frozen-lockfile
just env-init
just hooks-install
Expand All @@ -23,7 +25,7 @@ commit-check:
bun run commit:check

# Start the local development stack after applying local migrations.
dev:
dev: driver-submodule-check
just db-migrate
bun run dev

Expand Down Expand Up @@ -128,6 +130,10 @@ e2e *args:
driver-submodule-smoke:
bun run driver:submodule:smoke

# Verify that the Agent Driver checkout matches the repository gitlink.
driver-submodule-check:
bun run driver:submodule:check

# Update the Agent Driver submodule to upstream HEAD.
driver-update:
git submodule update --init --remote --checkout apps/driver
Expand Down
12 changes: 7 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,18 @@
],
"type": "module",
"scripts": {
"build": "vp run --filter agent-driver build && vp run --filter @mosoo/web build",
"build": "bun run driver:submodule:check && vp run --filter agent-driver build && vp run --filter @mosoo/web build",
"cf:types": "vp run --filter @mosoo/api cf:types",
"check": "vp run -w fmt:check && vp run -w docs:check && vp run -w lint && vp run -w tc && vp run -w test",
"check": "bun run driver:submodule:check && vp run -w fmt:check && vp run -w docs:check && vp run -w lint && vp run -w tc && vp run -w test",
"db:migrate:local": "vp run --filter @mosoo/api db:migrate:local",
"db:regen": "vp run --filter @mosoo/db db:regen",
"deploy": "vp run -w deploy:api && vp run -w deploy:web",
"deploy:api": "vp run --filter @mosoo/api deploy",
"deploy:api": "bun run driver:submodule:check && vp run --filter @mosoo/api deploy",
"deploy:web": "vp run --filter @mosoo/web deploy",
"dev": "vp run --filter @mosoo/api --filter @mosoo/web --parallel dev",
"dev": "bun run driver:submodule:check && vp run --filter @mosoo/api --filter @mosoo/web --parallel dev",
"docs:check": "vp exec bun scripts/check-doc-links.ts",
"driver:repo:export": "vp exec bun scripts/export-driver-standalone-repo.ts",
"driver:submodule:check": "bun scripts/check-driver-submodule-state.ts",
"driver:submodule:smoke": "vp exec bun scripts/check-driver-submodule-cutover.ts",
"e2e": "bun e2e/cli.ts",
"env:init": "vp run --filter @mosoo/api env:init",
Expand All @@ -35,7 +37,7 @@
"react-doctor:diff": "vp exec react-doctor apps/web --verbose --diff",
"react-doctor:report": "vp exec react-doctor apps/web --json --json-compact --full --fail-on none",
"tc": "vp run -r tc",
"test": "vp exec bun test config/commit-policy.test.ts scripts/validate-commit-message.test.ts && vp run --filter @mosoo/api --filter agent-driver --filter @mosoo/web --filter @mosoo/ag-ui-session --filter @mosoo/agent-package --filter @mosoo/contracts --filter @mosoo/db --filter @mosoo/id --filter @mosoo/public-api-client --filter @mosoo/runtime-catalog --filter @mosoo/runtime-events --filter @mosoo/session-policy --filter @mosoo/skill-package test && vp run -w graphql:codegen:check"
"test": "vp exec bun test config/commit-policy.test.ts scripts/check-driver-submodule-state.test.ts scripts/validate-commit-message.test.ts && vp run --filter @mosoo/api --filter agent-driver --filter @mosoo/web --filter @mosoo/ag-ui-session --filter @mosoo/agent-package --filter @mosoo/contracts --filter @mosoo/db --filter @mosoo/id --filter @mosoo/public-api-client --filter @mosoo/runtime-catalog --filter @mosoo/runtime-events --filter @mosoo/session-policy --filter @mosoo/skill-package test && vp run -w graphql:codegen:check"
},
"devDependencies": {
"@graphql-codegen/cli": "^7.2.0",
Expand Down
30 changes: 30 additions & 0 deletions scripts/check-driver-submodule-state.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { describe, expect, test } from "bun:test";

import { validateDriverSubmoduleCheckout } from "./check-driver-submodule-state";

describe("driver submodule checkout guard", () => {
test("accepts the commit recorded by the repository index", () => {
expect(() =>
validateDriverSubmoduleCheckout({
actualCommit: "expected-commit",
expectedCommit: "expected-commit",
}),
).not.toThrow();
});

test("rejects a stale driver checkout with an actionable command", () => {
expect(() =>
validateDriverSubmoduleCheckout({
actualCommit: "stale-commit",
expectedCommit: "expected-commit",
}),
).toThrow(
[
"apps/driver is checked out at the wrong commit.",
"Expected: expected-commit",
"Actual: stale-commit",
"Run: git submodule update --init --checkout apps/driver",
].join("\n"),
);
});
});
76 changes: 76 additions & 0 deletions scripts/check-driver-submodule-state.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { spawnSync } from "node:child_process";
import { fileURLToPath } from "node:url";

const driverSubmodulePath = "apps/driver";
const updateCommand = `git submodule update --init --checkout ${driverSubmodulePath}`;

export interface DriverSubmoduleCheckout {
readonly actualCommit: string;
readonly expectedCommit: string;
}

function fail(message: string): never {
throw new Error(`Driver submodule check failed: ${message}`);
}

function readGitOutput(repoRoot: string, args: readonly string[], failureMessage: string): string {
const result = spawnSync("git", [...args], {
cwd: repoRoot,
encoding: "utf8",
stdio: ["ignore", "pipe", "pipe"],
});

if (result.status !== 0) {
const detail = result.stderr.trim();
fail(`${failureMessage}${detail.length > 0 ? `\n${detail}` : ""}`);
}

const output = result.stdout.trim();

if (output.length === 0) {
fail(failureMessage);
}

return output;
}

export function validateDriverSubmoduleCheckout(input: DriverSubmoduleCheckout): void {
if (input.actualCommit === input.expectedCommit) {
return;
}

fail(
[
`${driverSubmodulePath} is checked out at the wrong commit.`,
`Expected: ${input.expectedCommit}`,
`Actual: ${input.actualCommit}`,
`Run: ${updateCommand}`,
].join("\n"),
);
}

export function checkDriverSubmoduleCheckout(repoRoot: string): DriverSubmoduleCheckout {
const expectedCommit = readGitOutput(
repoRoot,
["rev-parse", `:${driverSubmodulePath}`],
`${driverSubmodulePath} is not recorded as an initialized gitlink in the repository index.`,
);
const actualCommit = readGitOutput(
repoRoot,
["-C", driverSubmodulePath, "rev-parse", "HEAD"],
`${driverSubmodulePath} is not initialized. Run: ${updateCommand}`,
);
const checkout = {
actualCommit,
expectedCommit,
} satisfies DriverSubmoduleCheckout;

validateDriverSubmoduleCheckout(checkout);
return checkout;
}

if (import.meta.main) {
const repoRoot = fileURLToPath(new URL("..", import.meta.url));
const checkout = checkDriverSubmoduleCheckout(repoRoot);
console.log(`Driver submodule checkout matches ${checkout.expectedCommit}.`);
}
Loading