swallowkit 2.0.0-alpha.6 → 2.0.0-alpha.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/commands/provision.d.ts +2 -0
- package/dist/cli/commands/provision.d.ts.map +1 -1
- package/dist/cli/commands/provision.js +214 -109
- package/dist/cli/commands/provision.js.map +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/core/operations/provision-deployment.d.ts +7 -0
- package/dist/core/operations/provision-deployment.d.ts.map +1 -1
- package/dist/core/operations/provision-deployment.js +16 -3
- package/dist/core/operations/provision-deployment.js.map +1 -1
- package/dist/core/operations/provision-operations.d.ts +4 -0
- package/dist/core/operations/provision-operations.d.ts.map +1 -1
- package/dist/core/operations/provision-operations.js +8 -3
- package/dist/core/operations/provision-operations.js.map +1 -1
- package/dist/core/project/capabilities.js +3 -3
- package/dist/core/project/capabilities.js.map +1 -1
- package/dist/core/project/workflows.d.ts.map +1 -1
- package/dist/core/project/workflows.js +2 -0
- package/dist/core/project/workflows.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/agent-instructions.test.ts +2 -0
- package/src/__tests__/fixtures/azure-cli.cjs +10 -1
- package/src/__tests__/provision-runtime.test.ts +137 -2
- package/src/cli/commands/provision.ts +220 -108
- package/src/cli/index.ts +2 -2
- package/src/core/operations/provision-deployment.ts +17 -1
- package/src/core/operations/provision-operations.ts +17 -5
- package/src/core/project/agent-templates/AGENTS.md +4 -0
- package/src/core/project/agent-templates/CLAUDE.md +2 -0
- package/src/core/project/agent-templates/copilot-instructions.md +2 -0
- package/src/core/project/capabilities.ts +3 -3
- package/src/core/project/workflows.ts +2 -0
|
@@ -20,7 +20,7 @@ import { deletePlanState, listProvisionRuns, loadPlanState, loadProvisionRun, lo
|
|
|
20
20
|
import { hashFileIfExists } from "./file-session";
|
|
21
21
|
import {
|
|
22
22
|
DEFAULT_PROVISION_WAIT_SECONDS, DEPLOYMENT_QUERY, DeploymentObservation, DeploymentReference,
|
|
23
|
-
MAX_PROVISION_WAIT_SECONDS, queryAzureDeployment, queryDeploymentOperationErrors, waitForAzureDeployment,
|
|
23
|
+
MAX_PROVISION_WAIT_SECONDS, queryAzureDeployment, queryDeploymentOperationErrors, UNBOUNDED_WAIT_TRANSIENT_RETRIES, waitForAzureDeployment,
|
|
24
24
|
} from "./provision-deployment";
|
|
25
25
|
import {
|
|
26
26
|
MIGRATION_MANIFEST_PATH,
|
|
@@ -625,6 +625,8 @@ export interface ApplyProvisionOptions {
|
|
|
625
625
|
planId: string;
|
|
626
626
|
approve?: boolean;
|
|
627
627
|
waitSeconds?: number;
|
|
628
|
+
/** Human CLI: keep polling until Azure reaches a terminal state instead of using the bounded wait budget. */
|
|
629
|
+
waitUntilComplete?: boolean;
|
|
628
630
|
}
|
|
629
631
|
|
|
630
632
|
export interface ApplyProvisionResult {
|
|
@@ -848,7 +850,10 @@ export async function applyProvisionOperation(options: ApplyProvisionOptions): P
|
|
|
848
850
|
);
|
|
849
851
|
}
|
|
850
852
|
|
|
851
|
-
const result = await executeProvisionPlan(plan, {
|
|
853
|
+
const result = await executeProvisionPlan(plan, {
|
|
854
|
+
approve: options.approve, waitSeconds: options.waitSeconds, waitUntilComplete: options.waitUntilComplete,
|
|
855
|
+
retryHint: MACHINE_RETRY_HINT, projectRoot,
|
|
856
|
+
});
|
|
852
857
|
if (result.status === "complete") {
|
|
853
858
|
try { deletePlanState(plan.planId, projectRoot); } catch {
|
|
854
859
|
result.warnings.push("Azure and migration bookkeeping completed, but the old preview could not be removed. The completed execution checkpoint prevents replay.");
|
|
@@ -863,11 +868,17 @@ export async function applyProvisionOperation(options: ApplyProvisionOptions): P
|
|
|
863
868
|
*/
|
|
864
869
|
export async function executeProvisionPlan(
|
|
865
870
|
plan: ProvisionPlanData,
|
|
866
|
-
options: {
|
|
871
|
+
options: {
|
|
872
|
+
approve?: boolean; retryHint?: string; projectRoot?: string; waitSeconds?: number;
|
|
873
|
+
/** Human CLI only: no overall deadline; each az call stays bounded and the checkpoint stays resumable. */
|
|
874
|
+
waitUntilComplete?: boolean;
|
|
875
|
+
signal?: AbortSignal; pollIntervalMs?: number;
|
|
876
|
+
} = {}
|
|
867
877
|
): Promise<ApplyProvisionResult> {
|
|
868
878
|
const projectRoot = options.projectRoot ?? process.cwd();
|
|
869
879
|
const retryHint = options.retryHint ?? MACHINE_RETRY_HINT;
|
|
870
|
-
const
|
|
880
|
+
const waitUntilComplete = options.waitUntilComplete === true && options.waitSeconds === undefined;
|
|
881
|
+
const waitSeconds = waitUntilComplete ? 0 : validateWaitSeconds(options.waitSeconds);
|
|
871
882
|
if (!options.approve) {
|
|
872
883
|
throw new MachineCommandError(
|
|
873
884
|
"approval-required",
|
|
@@ -937,7 +948,7 @@ export async function executeProvisionPlan(
|
|
|
937
948
|
options.signal?.addEventListener("abort", externalAbort, { once: true });
|
|
938
949
|
if (options.signal?.aborted) controller.abort();
|
|
939
950
|
const signal = controller.signal;
|
|
940
|
-
const deadline = Date.now() + waitSeconds * 1_000;
|
|
951
|
+
const deadline = waitUntilComplete ? Number.POSITIVE_INFINITY : Date.now() + waitSeconds * 1_000;
|
|
941
952
|
const persist = () => {
|
|
942
953
|
if (!run) return;
|
|
943
954
|
run.warnings = run.warnings.slice(-20);
|
|
@@ -958,6 +969,7 @@ export async function executeProvisionPlan(
|
|
|
958
969
|
...(signal.aborted ? {} : { signal }),
|
|
959
970
|
...(signal.aborted ? { queryTimeoutMs: 5_000 } : {}),
|
|
960
971
|
pollIntervalMs: options.pollIntervalMs,
|
|
972
|
+
...(waitUntilComplete ? { transientRetries: UNBOUNDED_WAIT_TRANSIENT_RETRIES } : {}),
|
|
961
973
|
secretValues,
|
|
962
974
|
onObservation: (value) => {
|
|
963
975
|
run!.observation = value;
|
|
@@ -224,6 +224,10 @@ required.
|
|
|
224
224
|
|
|
225
225
|
Never invent or implicitly grant human approval.
|
|
226
226
|
|
|
227
|
+
Humans normally invoke `swallowkit provision` directly. Its invocation requests
|
|
228
|
+
execution without an additional confirmation. Agents must still use the
|
|
229
|
+
machine/MCP approval flow and must not switch to normal CLI to bypass it.
|
|
230
|
+
|
|
227
231
|
## Model Changes
|
|
228
232
|
|
|
229
233
|
For an existing model change, the normal pattern is:
|
|
@@ -24,6 +24,8 @@ Always-on rules:
|
|
|
24
24
|
after apply).
|
|
25
25
|
- Use plan/apply for deterministic generation.
|
|
26
26
|
- Respect all `requires-human` states and provisioning approval gates.
|
|
27
|
+
- Normal `swallowkit provision` is for humans. Agents must not use it to bypass
|
|
28
|
+
the machine/MCP approval flow.
|
|
27
29
|
- Provision timeouts/Ctrl+C do not prove Azure failed. Inspect the original
|
|
28
30
|
execution checkpoint with `machine inspect provision --plan <runId>`; resume
|
|
29
31
|
`machine apply provision --plan <runId> --approve` only after explicit human
|
|
@@ -23,6 +23,8 @@ Key rules:
|
|
|
23
23
|
after apply).
|
|
24
24
|
- Use plan/apply for deterministic generation.
|
|
25
25
|
- Respect `requires-human` states and other human approval gates.
|
|
26
|
+
- Normal `swallowkit provision` is a human-facing deployment command. Agents must
|
|
27
|
+
use the machine/MCP approval flow, not normal CLI as an approval bypass.
|
|
26
28
|
- Provision timeouts/Ctrl+C do not prove Azure failed. Read `status`, `outcome`,
|
|
27
29
|
and `nextActions`; inspect the original run with `machine inspect provision
|
|
28
30
|
--plan <runId>`, then resume `machine apply provision --plan <runId> --approve`
|
|
@@ -233,12 +233,12 @@ export function inspectCapabilities(): CapabilitiesContract {
|
|
|
233
233
|
"(regular CLI) configure-mcp [--version auto|latest|<semver>] — re-select the MCP launcher version in .mcp.json",
|
|
234
234
|
],
|
|
235
235
|
provisioning: {
|
|
236
|
-
execution: "Submit Bicep once with az deployment group create --no-wait, then bounded state polling (default 300 seconds, configurable 0-3600). Azure CLI invocations are bounded separately. Warning-only stderr with exit 0 is not a failure; output capture limits do not terminate az.",
|
|
236
|
+
execution: "Submit Bicep once with az deployment group create --no-wait, then bounded state polling (default 300 seconds, configurable 0-3600) for machine/MCP; the human `swallowkit provision` command waits until Azure reaches a terminal state. Azure CLI invocations are bounded separately. Warning-only stderr with exit 0 is not a failure; output capture limits do not terminate az.",
|
|
237
237
|
completion: "status complete/outcome succeeded requires Azure Succeeded plus verified migration tags and local ledger completion. Running/Accepted -> in-progress; unreadable/not-found state -> blocked/outcome unknown; bookkeeping interruption after Azure Succeeded -> blocked/outcome partial; Failed/Canceled -> failed with Azure causes.",
|
|
238
238
|
tracking: "Approved runs persist before Azure writes under .swallowkit/state/provision/. runId equals the original planId and preserves the subscription, RG, deployment ID/correlation, fingerprints and migration state. inspect provision is read-only; apply provision --plan resumes without re-submitting attempted deployments. Ctrl+C/termination may leave Azure running; never cancel/delete without explicit consent.",
|
|
239
239
|
recovery: "For an older untracked baseline, plan provision --resume-deployment <name> compares the existing ARM template and non-secure parameters to the local Bicep/parameters. It observes that deployment and only tags/records it after Succeeded. Mismatches, unreadable evidence, secure parameters or non-baseline migrations block; do not use reconcile just to repair bookkeeping.",
|
|
240
|
-
diagnostics: "
|
|
241
|
-
approval: "
|
|
240
|
+
diagnostics: "Machine/MCP results include bounded/redacted stdout/stderr, omitted-output flags, exit code, signal, failure kind, elapsed time and deployment identity, but no deployment outputs. Normal CLI shows named resource information and CI/CD setup guidance after success. Never print --debug output, keys, tokens or connection strings.",
|
|
241
|
+
approval: "Machine/MCP initial apply and every resume require explicit human approval. A human invoking normal provision or provision --resume explicitly requests execution without another confirmation prompt. Agents must not switch to normal CLI to bypass approval. A passing local command or an ok envelope is not proof of completed Azure provisioning; inspect status, outcome and nextActions.",
|
|
242
242
|
},
|
|
243
243
|
verifyChecks: {
|
|
244
244
|
defaultChecks: ["structure", "drift", "typecheck", "backend-build"],
|
|
@@ -211,6 +211,8 @@ Goal: bootstrap Azure once, then apply only pending versioned infrastructure mig
|
|
|
211
211
|
\`status: "requires-human"\` and \`requiresApproval: true\` by design.
|
|
212
212
|
- Never pass \`--approve\` to \`apply provision\` unless a human explicitly
|
|
213
213
|
instructed you to provision in this session.
|
|
214
|
+
- This plan/apply workflow is for agents. Humans normally run \`swallowkit provision\`
|
|
215
|
+
directly; do not switch to that command to bypass the agent approval gate.
|
|
214
216
|
- Inspect infra locally first — no \`az\` calls are needed for inspection.
|
|
215
217
|
- Never edit an applied migration. Create a corrective migration instead.
|
|
216
218
|
- Never use \`--reconcile\` for an ordinary model or resource addition.
|