Skip to content
Merged
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
35 changes: 17 additions & 18 deletions SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,14 @@ description: >
# GitHub Delivery

Own GitHub work from product intake through merged PR. Natural language is the
public API; scripts and policy modules are internal evidence/safety machinery.
public API; internals enforce bounded progress and evidence/context economy.

## Route

Match the request, then load **only** the selected workflow plus the policy
modules declared at the top of that workflow. Do **not** load
`references/shared-rules.md` as mandatory context; it is now a compatibility
index. Every routed workflow includes `policy-kernel` plus only the domains it
needs.
index. Each route includes `policy-kernel` plus only needed domains.

**Full-review routing is explicit:** when the user asks for a full review, route
to `references/full-review-pr.md`; bot-fix, CodeRabbit, Codex, security, or
Expand Down Expand Up @@ -93,18 +92,19 @@ individual PR's review/fix/readiness bar.

## Policy loading contract

1. Read `references/policy-kernel.md`.
2. Read the selected workflow's `<!-- policy-modules:start -->` declaration.
3. Load each unconditional module from `references/policy/<name>.md`.
4. Load a conditional module only when its stated observable condition is true.
5. Use `node scripts/policy-bundle.mjs <workflow>` when deterministic bundle
resolution/inspection is useful; `--validate` checks the architecture.
6. Canonical `GD-*` rules are defined once in the kernel/modules. Workflow prose
may add ordering and workflow-specific contracts but must not weaken them.
Load `references/policy-kernel.md`, the selected workflow's unconditional
modules, and conditionals only when their observable condition is true.
`node scripts/policy-bundle.mjs <workflow>` resolves/validates this bundle.
Workflows cannot weaken `GD-*` rules. GD-CORE-001 through GD-CORE-010 remain mandatory.

Core invariants are GD-CORE-001 through GD-CORE-010. They cover fail-closed
evidence, locked scope, gate integrity, untrusted repository instructions, live
state, write authority, final evidence, bounded progress, and evidence/context economy.
## Workflow controller contract

After routing, run `node scripts/workflow-brief.mjs <workflow>` once and use one
persistent `delivery-controller.mjs` checkpoint. Route/phase graph stay locked;
the controller owns transitions, evidence/retry/resource/no-progress accounting
and resume. Only phase/state/blocker/required-evidence/execution change is
progress. Conditional policy extends unchanged context. The controller grants
no GitHub write authority.

## Mandatory entrypoint behavior

Expand Down Expand Up @@ -164,7 +164,6 @@ expected absences and rejected values. One representative member is insufficient

## Safety precedence

Policy kernel/modules and executable gates are stricter than workflow prose. A
workflow may add requirements but cannot waive a canonical rule. If two runtime
instructions genuinely conflict and the stricter safe behavior is not clear,
fail closed and surface the contradiction rather than inventing authority.
Kernel/modules and executable gates override workflow prose; workflows cannot
waive canonical rules. If runtime instructions genuinely conflict and the
stricter safe behavior is unclear, fail closed and surface the contradiction.
184 changes: 184 additions & 0 deletions scripts/delivery-controller.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
#!/usr/bin/env node
import { resolve } from "node:path";

import {
createDeliveryWorkflowController,
readDeliveryWorkflowCheckpoint,
writeDeliveryWorkflowCheckpoint,
} from "./lib/delivery-workflow-controller.mjs";
import { resolveDeliveryWorkflowProfile } from "./lib/delivery-workflow-profiles.mjs";

const USAGE = `Usage:
node scripts/delivery-controller.mjs start WORKFLOW --repo OWNER/REPO --checkpoint FILE [--issue N] [--pr N] [--base SHA] [--head SHA]
node scripts/delivery-controller.mjs transition CHECKPOINT PHASE
node scripts/delivery-controller.mjs cycle CHECKPOINT [--state-changed] [--blocker-removed] [--required-evidence-produced] [--execution-completed]
node scripts/delivery-controller.mjs retry CHECKPOINT
node scripts/delivery-controller.mjs evidence-action CHECKPOINT
node scripts/delivery-controller.mjs usage CHECKPOINT --workflow-tokens N --phase-tokens N
node scripts/delivery-controller.mjs refs CHECKPOINT [--base SHA] [--head SHA]
node scripts/delivery-controller.mjs blocker-add CHECKPOINT BLOCKER
node scripts/delivery-controller.mjs blocker-remove CHECKPOINT BLOCKER
node scripts/delivery-controller.mjs show CHECKPOINT`;

function positiveInteger(value, label) {
const parsed = Number(value);
if (!Number.isInteger(parsed) || parsed <= 0) throw new Error(`${label} requires a positive integer`);
return parsed;
}

function nonNegativeInteger(value, label) {
const parsed = Number(value);
if (!Number.isInteger(parsed) || parsed < 0) throw new Error(`${label} requires a non-negative integer`);
return parsed;
}

function takeOption(argv, name) {
const index = argv.indexOf(name);
if (index < 0) return null;
if (index + 1 >= argv.length) throw new Error(`${name} requires a value`);
const value = argv[index + 1];
argv.splice(index, 2);
return value;
}

function takeFlag(argv, name) {
const index = argv.indexOf(name);
if (index < 0) return false;
argv.splice(index, 1);
return true;
}

function assertEmpty(argv) {
if (argv.length) throw new Error(`Unknown arguments: ${argv.join(" ")}\n${USAGE}`);
}

function load(path) {
const checkpoint = resolve(path);
const snapshot = readDeliveryWorkflowCheckpoint(checkpoint);
const profile = resolveDeliveryWorkflowProfile(snapshot.workflow);
return {
checkpoint,
controller: createDeliveryWorkflowController({
snapshot,
graph: profile.graph,
}),
};
}

function persist(loaded) {
const snapshot = loaded.controller.snapshot();
writeDeliveryWorkflowCheckpoint(loaded.checkpoint, snapshot);
return snapshot;
}

function print(payload) {
process.stdout.write(`${JSON.stringify(payload, null, 2)}\n`);
}

try {
const argv = process.argv.slice(2);
const command = argv.shift();
if (!command) throw new Error(USAGE);

if (command === "start") {
const workflow = argv.shift();
if (!workflow) throw new Error(USAGE);
const repo = takeOption(argv, "--repo");
const checkpointValue = takeOption(argv, "--checkpoint");
const issueRaw = takeOption(argv, "--issue");
const prRaw = takeOption(argv, "--pr");
const baseSha = takeOption(argv, "--base");
const headSha = takeOption(argv, "--head");
assertEmpty(argv);
if (!repo || !checkpointValue) throw new Error("start requires --repo and --checkpoint");
const profile = resolveDeliveryWorkflowProfile(workflow);
const checkpoint = resolve(checkpointValue);
const controller = createDeliveryWorkflowController({
workflow: profile.workflow,
repo,
issue: issueRaw === null ? null : positiveInteger(issueRaw, "--issue"),
pr: prRaw === null ? null : positiveInteger(prRaw, "--pr"),
baseSha,
headSha,
graph: profile.graph,
startPhase: profile.startPhase,
});
const snapshot = controller.snapshot();
writeDeliveryWorkflowCheckpoint(checkpoint, snapshot);
print(snapshot);
} else if (command === "show") {
const checkpoint = argv.shift();
if (!checkpoint) throw new Error(USAGE);
assertEmpty(argv);
print(readDeliveryWorkflowCheckpoint(resolve(checkpoint)));
} else {
const checkpointValue = argv.shift();
if (!checkpointValue) throw new Error(USAGE);
const loaded = load(checkpointValue);
let result;

if (command === "transition") {
const phase = argv.shift();
if (!phase) throw new Error(USAGE);
assertEmpty(argv);
result = loaded.controller.transition(phase);
} else if (command === "cycle") {
const signal = {
stateChanged: takeFlag(argv, "--state-changed"),
blockerRemoved: takeFlag(argv, "--blocker-removed"),
requiredEvidenceProduced: takeFlag(argv, "--required-evidence-produced"),
executionCompleted: takeFlag(argv, "--execution-completed"),
};
assertEmpty(argv);
result = loaded.controller.observeCycle(signal);
} else if (command === "retry") {
assertEmpty(argv);
result = loaded.controller.recordPhaseRetry();
} else if (command === "evidence-action") {
assertEmpty(argv);
result = loaded.controller.recordEvidenceAction();
} else if (command === "usage") {
const workflowTokens = takeOption(argv, "--workflow-tokens");
const phaseTokens = takeOption(argv, "--phase-tokens");
assertEmpty(argv);
result = loaded.controller.observeResourceUsage({
workflowTokens: workflowTokens === null ? undefined : nonNegativeInteger(workflowTokens, "--workflow-tokens"),
phaseTokens: phaseTokens === null ? undefined : nonNegativeInteger(phaseTokens, "--phase-tokens"),
});
} else if (command === "refs") {
const baseSha = takeOption(argv, "--base");
const headSha = takeOption(argv, "--head");
assertEmpty(argv);
result = loaded.controller.updateRefs({
...(baseSha !== null ? { baseSha } : {}),
...(headSha !== null ? { headSha } : {}),
});
} else if (command === "blocker-add") {
const blocker = argv.shift();
if (!blocker) throw new Error(USAGE);
assertEmpty(argv);
result = loaded.controller.addBlocker(blocker);
} else if (command === "blocker-remove") {
const blocker = argv.shift();
if (!blocker) throw new Error(USAGE);
assertEmpty(argv);
result = { removed: loaded.controller.removeBlocker(blocker) };
} else {
throw new Error(USAGE);
}

const snapshot = persist(loaded);
print({
schemaVersion: 1,
kind: "github-delivery/workflow-controller-command",
command,
result,
snapshot,
});
if (result?.action === "interrupt") process.exitCode = 3;
else if (result?.action === "restrict-evidence") process.exitCode = 4;
}
} catch (error) {
console.error(String(error?.message || error));
process.exitCode = 2;
}
Loading