@loucompanion/forge-bridge 0.1.3-dev.b6be5e7f9668 → 0.1.3-dev.ba293ccf876b
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/README.md +127 -0
- package/dist/bridge/bridge.base.d.ts +8 -1
- package/dist/bridge/bridge.service.d.ts +98 -3
- package/dist/bridge/bridge.service.js +1445 -48
- package/dist/bridge/bridge.types.d.ts +209 -1
- package/dist/bridge/readiness-result-outbox.d.ts +21 -0
- package/dist/bridge/readiness-result-outbox.js +54 -0
- package/dist/bridge/readiness-result-worker.d.ts +2 -0
- package/dist/bridge/readiness-result-worker.js +100 -0
- package/dist/bridge/runner-host-capabilities.d.ts +15 -0
- package/dist/bridge/runner-host-capabilities.js +93 -0
- package/dist/cleanup/cleanup.service.d.ts +14 -2
- package/dist/cleanup/cleanup.service.js +496 -3
- package/dist/cleanup/cleanup.types.d.ts +10 -0
- package/dist/cleanup/index.d.ts +1 -1
- package/dist/cleanup/index.js +1 -1
- package/dist/cleanup/internals.d.ts +2 -2
- package/dist/cleanup/internals.js +1 -1
- package/dist/cli/cli.help.d.ts +2 -0
- package/dist/cli/cli.help.js +217 -0
- package/dist/cli/cli.service.d.ts +45 -2
- package/dist/cli/cli.service.js +383 -209
- package/dist/cli/local-config.d.ts +7 -0
- package/dist/cli/local-config.js +51 -3
- package/dist/runtime/aspnet-runtime-prebuild.d.ts +36 -0
- package/dist/runtime/aspnet-runtime-prebuild.js +340 -0
- package/dist/runtime/attempt-node-runtime-launcher.d.ts +17 -0
- package/dist/runtime/attempt-node-runtime-launcher.js +105 -0
- package/dist/runtime/attempt-path-operation.d.ts +21 -0
- package/dist/runtime/attempt-path-operation.js +94 -0
- package/dist/runtime/attempt-private-directory.d.ts +6 -0
- package/dist/runtime/attempt-private-directory.js +54 -0
- package/dist/runtime/attempt-process-supervisor-registry.d.ts +20 -0
- package/dist/runtime/attempt-process-supervisor-registry.js +64 -0
- package/dist/runtime/attempt-process-supervisor.d.ts +97 -0
- package/dist/runtime/attempt-process-supervisor.js +386 -0
- package/dist/runtime/canonical-source-file.d.ts +3 -0
- package/dist/runtime/canonical-source-file.js +54 -0
- package/dist/runtime/docker-engine-probe.d.ts +83 -0
- package/dist/runtime/docker-engine-probe.js +300 -0
- package/dist/runtime/generated-output-reset.d.ts +10 -0
- package/dist/runtime/generated-output-reset.js +103 -0
- package/dist/runtime/host-diagnostics.d.ts +4 -0
- package/dist/runtime/host-diagnostics.js +95 -0
- package/dist/runtime/host-listener-inspector.d.ts +46 -0
- package/dist/runtime/host-listener-inspector.js +349 -0
- package/dist/runtime/host-port-broker.d.ts +76 -0
- package/dist/runtime/host-port-broker.js +333 -0
- package/dist/runtime/host-runtime-contract.d.ts +56 -0
- package/dist/runtime/host-runtime-contract.js +709 -0
- package/dist/runtime/host-runtime-lease.d.ts +201 -0
- package/dist/runtime/host-runtime-lease.js +2314 -0
- package/dist/runtime/host-runtime-promotion.d.ts +32 -0
- package/dist/runtime/host-runtime-promotion.js +206 -0
- package/dist/runtime/memory-capacity.d.ts +68 -0
- package/dist/runtime/memory-capacity.js +121 -0
- package/dist/runtime/node-host-runtime-adapter.d.ts +54 -0
- package/dist/runtime/node-host-runtime-adapter.js +284 -0
- package/dist/runtime/pinned-directory-process.d.ts +4 -0
- package/dist/runtime/pinned-directory-process.js +20 -0
- package/dist/runtime/pinned-source-directory.d.ts +9 -0
- package/dist/runtime/pinned-source-directory.js +56 -0
- package/dist/runtime/playwright-host-runtime-adapter.d.ts +21 -0
- package/dist/runtime/playwright-host-runtime-adapter.js +268 -0
- package/dist/runtime/prepared-runtime-identity.d.ts +3 -0
- package/dist/runtime/prepared-runtime-identity.js +191 -0
- package/dist/runtime/prepared-runtime-readiness.d.ts +22 -0
- package/dist/runtime/prepared-runtime-readiness.js +191 -0
- package/dist/runtime/runtime-isolation-lease.d.ts +67 -0
- package/dist/runtime/runtime-isolation-lease.js +158 -0
- package/dist/runtime/workspace-resource-estimator.d.ts +17 -0
- package/dist/runtime/workspace-resource-estimator.js +174 -0
- package/dist/sandbox/command-runner.d.ts +4 -0
- package/dist/sandbox/command-runner.js +47 -0
- package/dist/sandbox/contract.d.ts +5 -0
- package/dist/sandbox/contract.js +276 -0
- package/dist/sandbox/event-budget.d.ts +11 -0
- package/dist/sandbox/event-budget.js +27 -0
- package/dist/sandbox/image-policy.d.ts +35 -0
- package/dist/sandbox/image-policy.js +247 -0
- package/dist/sandbox/index.d.ts +5 -0
- package/dist/sandbox/index.js +5 -0
- package/dist/sandbox/lease-watchdog.d.ts +18 -0
- package/dist/sandbox/lease-watchdog.js +67 -0
- package/dist/sandbox/preflight.d.ts +84 -0
- package/dist/sandbox/preflight.js +521 -0
- package/dist/sandbox/process.d.ts +20 -0
- package/dist/sandbox/process.js +209 -0
- package/dist/sandbox/provider-auth/codex.d.ts +26 -0
- package/dist/sandbox/provider-auth/codex.js +212 -0
- package/dist/sandbox/repository-lock.d.ts +5 -0
- package/dist/sandbox/repository-lock.js +121 -0
- package/dist/sandbox/runtime.d.ts +297 -0
- package/dist/sandbox/runtime.js +2338 -0
- package/dist/sandbox/sandbox.types.d.ts +93 -0
- package/dist/sandbox/sandbox.types.js +1 -0
- package/dist/sandbox/smoke.d.ts +76 -0
- package/dist/sandbox/smoke.js +380 -0
- package/dist/sandbox/worker-supervisor.d.ts +13 -0
- package/dist/sandbox/worker-supervisor.js +36 -0
- package/dist/sandbox/worker.d.ts +1 -0
- package/dist/sandbox/worker.js +225 -0
- package/dist/sandbox/workspace.service.d.ts +13 -0
- package/dist/sandbox/workspace.service.js +72 -0
- package/dist/session/managed-attempt-tools.d.ts +21 -0
- package/dist/session/managed-attempt-tools.js +912 -0
- package/dist/session/managed-build-coordinator.d.ts +5 -0
- package/dist/session/managed-build-coordinator.js +105 -0
- package/dist/session/managed-build-receipt.d.ts +21 -0
- package/dist/session/managed-build-receipt.js +335 -0
- package/dist/session/phase-completion.artifacts.d.ts +27 -0
- package/dist/session/phase-completion.artifacts.js +829 -0
- package/dist/session/phase-completion.d.ts +44 -46
- package/dist/session/phase-completion.helpers.d.ts +117 -0
- package/dist/session/phase-completion.helpers.js +701 -0
- package/dist/session/phase-completion.js +42 -3488
- package/dist/session/phase-completion.prompts.d.ts +14 -0
- package/dist/session/phase-completion.prompts.js +236 -0
- package/dist/session/phase-completion.runtime.d.ts +48 -0
- package/dist/session/phase-completion.runtime.js +790 -0
- package/dist/session/phase-completion.schemas.d.ts +3 -0
- package/dist/session/phase-completion.schemas.js +820 -0
- package/dist/session/phase-completion.validation.d.ts +37 -0
- package/dist/session/phase-completion.validation.js +855 -0
- package/dist/session/pre-publication-validation.d.ts +47 -0
- package/dist/session/pre-publication-validation.js +249 -0
- package/dist/session/provider-cli/ci-repair-readiness.d.ts +16 -0
- package/dist/session/provider-cli/ci-repair-readiness.js +110 -0
- package/dist/session/provider-cli/provider-cli.artifacts.d.ts +94 -0
- package/dist/session/provider-cli/provider-cli.artifacts.js +812 -0
- package/dist/session/provider-cli/provider-cli.base.d.ts +1 -0
- package/dist/session/provider-cli/provider-cli.deterministic-payloads.d.ts +12 -0
- package/dist/session/provider-cli/provider-cli.deterministic-payloads.js +279 -0
- package/dist/session/provider-cli/provider-cli.deterministic.d.ts +14 -0
- package/dist/session/provider-cli/provider-cli.deterministic.js +377 -0
- package/dist/session/provider-cli/provider-cli.process.d.ts +57 -0
- package/dist/session/provider-cli/provider-cli.process.js +716 -0
- package/dist/session/provider-cli/provider-cli.prompts.d.ts +47 -0
- package/dist/session/provider-cli/provider-cli.prompts.js +611 -0
- package/dist/session/provider-cli/provider-cli.qa-sidecars.d.ts +11 -0
- package/dist/session/provider-cli/provider-cli.qa-sidecars.js +66 -0
- package/dist/session/provider-cli/provider-cli.repair-epoch.d.ts +6 -0
- package/dist/session/provider-cli/provider-cli.repair-epoch.js +11 -0
- package/dist/session/provider-cli/provider-cli.runtime.d.ts +9 -0
- package/dist/session/provider-cli/provider-cli.runtime.js +43 -0
- package/dist/session/provider-cli/provider-cli.service.d.ts +29 -53
- package/dist/session/provider-cli/provider-cli.service.js +640 -2581
- package/dist/session/provider-cli/provider-cli.types.d.ts +6 -0
- package/dist/session/provider-cli/provider-output-state.d.ts +22 -0
- package/dist/session/provider-cli/provider-output-state.js +520 -0
- package/dist/session/provider-cli/provider-usage.d.ts +7 -0
- package/dist/session/provider-cli/provider-usage.js +28 -5
- package/dist/session/session-redaction.d.ts +3 -0
- package/dist/session/session-redaction.js +38 -0
- package/dist/session/session.base.d.ts +6 -1
- package/dist/session/session.service.d.ts +8 -2
- package/dist/session/session.service.js +550 -58
- package/dist/session/session.types.d.ts +180 -1
- package/dist/session/session.types.js +323 -4
- package/dist/shared/format/format-bytes.d.ts +1 -0
- package/dist/shared/format/format-bytes.js +9 -0
- package/dist/shared/git/git.js +2 -1
- package/dist/shared/path/path.d.ts +1 -0
- package/dist/shared/path/path.js +21 -1
- package/dist/shared/process/dotnet-toolchain.d.ts +14 -0
- package/dist/shared/process/dotnet-toolchain.js +179 -0
- package/dist/shared/process/host-process-recovery.d.ts +12 -0
- package/dist/shared/process/host-process-recovery.js +78 -0
- package/dist/shared/process/host-process-supervisor.d.ts +59 -0
- package/dist/shared/process/host-process-supervisor.js +330 -0
- package/dist/shared/process/process.d.ts +2 -0
- package/dist/shared/process/process.js +11 -6
- package/dist/shared/process/windows-launch.d.ts +8 -0
- package/dist/shared/process/windows-launch.js +41 -0
- package/dist/shared/provider-capabilities.d.ts +1 -0
- package/dist/shared/provider-capabilities.js +3 -0
- package/dist/shared/redaction/redaction.js +16 -4
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/worktree/artifact-injector.d.ts +3 -2
- package/dist/worktree/artifact-injector.js +82 -10
- package/dist/worktree/dependency-warmer.d.ts +39 -1
- package/dist/worktree/dependency-warmer.js +351 -8
- package/dist/worktree/index.d.ts +2 -1
- package/dist/worktree/index.js +1 -0
- package/dist/worktree/prior-phase-artifact-hydrator.d.ts +2 -0
- package/dist/worktree/prior-phase-artifact-hydrator.js +136 -0
- package/dist/worktree/worktree-paths.d.ts +4 -0
- package/dist/worktree/worktree-paths.js +30 -0
- package/dist/worktree/worktree.base.d.ts +3 -0
- package/dist/worktree/worktree.service.d.ts +16 -3
- package/dist/worktree/worktree.service.js +323 -54
- package/dist/worktree/worktree.types.d.ts +5 -1
- package/package.json +8 -4
- package/runtime/windows-job-supervisor.ps1 +444 -0
- package/runtime/windows-listener-owner.ps1 +33 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { ProviderProcessRunner } from "./provider-cli/provider-cli.process.js";
|
|
2
|
+
import type { RunnerDispatchEvent } from "./session.types.js";
|
|
3
|
+
export type PrePublicationProfile = "implementation" | "comment_repair" | "ci_repair" | "conflict_repair";
|
|
4
|
+
interface ValidationStep {
|
|
5
|
+
readonly command: string;
|
|
6
|
+
readonly fallbackCommand?: string;
|
|
7
|
+
readonly args: readonly string[];
|
|
8
|
+
readonly fallbackArgs?: readonly string[];
|
|
9
|
+
readonly assertUnchangedPaths?: readonly string[];
|
|
10
|
+
}
|
|
11
|
+
interface ValidationCheck {
|
|
12
|
+
readonly id: string;
|
|
13
|
+
readonly profiles: readonly string[];
|
|
14
|
+
readonly changedPathPatterns: readonly string[];
|
|
15
|
+
readonly requiredCapability?: string;
|
|
16
|
+
readonly providerOnly?: boolean;
|
|
17
|
+
readonly steps: readonly ValidationStep[];
|
|
18
|
+
}
|
|
19
|
+
interface ValidationContract {
|
|
20
|
+
readonly schemaVersion: number;
|
|
21
|
+
readonly contractId: string;
|
|
22
|
+
readonly checks: readonly ValidationCheck[];
|
|
23
|
+
}
|
|
24
|
+
export interface PrePublicationCommandResult {
|
|
25
|
+
readonly exitCode: number;
|
|
26
|
+
readonly stdout?: string;
|
|
27
|
+
readonly stderr?: string;
|
|
28
|
+
}
|
|
29
|
+
export interface PrePublicationCommandRunner {
|
|
30
|
+
run(command: string, args: readonly string[], cwd: string, signal?: AbortSignal, environment?: Readonly<Record<string, string>>): Promise<PrePublicationCommandResult>;
|
|
31
|
+
}
|
|
32
|
+
export interface PrePublicationExecutionContext {
|
|
33
|
+
readonly baselineRevision?: string;
|
|
34
|
+
readonly environment?: Readonly<Record<string, string>>;
|
|
35
|
+
readonly processRunner?: ProviderProcessRunner;
|
|
36
|
+
}
|
|
37
|
+
export declare class PrePublicationValidator {
|
|
38
|
+
private readonly commands;
|
|
39
|
+
constructor(commands?: PrePublicationCommandRunner);
|
|
40
|
+
validate(worktreePath: string, profile: PrePublicationProfile, capabilities: ReadonlySet<string>, emit?: (event: RunnerDispatchEvent) => Promise<void>, signal?: AbortSignal, execution?: PrePublicationExecutionContext): Promise<readonly string[]>;
|
|
41
|
+
private changedPaths;
|
|
42
|
+
private runStep;
|
|
43
|
+
private runCommand;
|
|
44
|
+
}
|
|
45
|
+
export declare function applicableChecks(contract: ValidationContract, profile: PrePublicationProfile | "github_actions", changedPaths: readonly string[]): readonly ValidationCheck[];
|
|
46
|
+
export declare function loadValidationContract(worktreePath: string): Promise<ValidationContract | null>;
|
|
47
|
+
export {};
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
3
|
+
import fs from "node:fs/promises";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { promisify } from "node:util";
|
|
6
|
+
const execFileAsync = promisify(execFile);
|
|
7
|
+
const contractRelativePath = ".forge/validation/ci-parity.v1.json";
|
|
8
|
+
const requiredCheckIds = new Set([
|
|
9
|
+
"file-size-inventory",
|
|
10
|
+
"owned-suite-registration",
|
|
11
|
+
"dotnet-build-and-unit",
|
|
12
|
+
"openapi-and-generated-types",
|
|
13
|
+
"client",
|
|
14
|
+
"bridge",
|
|
15
|
+
"playwright-e2e",
|
|
16
|
+
"github-provider-policy",
|
|
17
|
+
]);
|
|
18
|
+
const approvedContractDigest = "014727b066b2b659b8772987650b85540f1bf70864c678187fde108a9b1d84d3";
|
|
19
|
+
class ProcessPrePublicationCommandRunner {
|
|
20
|
+
async run(command, args, cwd, signal, environment) {
|
|
21
|
+
try {
|
|
22
|
+
const windowsBatch = process.platform === "win32" && (command === "npm" || command === "pnpm");
|
|
23
|
+
const executable = windowsBatch ? (process.env.ComSpec ?? "cmd.exe") : command;
|
|
24
|
+
const commandArgs = windowsBatch
|
|
25
|
+
? ["/d", "/s", "/c", [`${command}.cmd`, ...args].map(quoteWindowsCommandArgument).join(" ")]
|
|
26
|
+
: [...args];
|
|
27
|
+
const result = await execFileAsync(executable, commandArgs, {
|
|
28
|
+
cwd,
|
|
29
|
+
encoding: "utf8",
|
|
30
|
+
maxBuffer: 4 * 1024 * 1024,
|
|
31
|
+
signal,
|
|
32
|
+
env: environment ? { ...process.env, ...environment } : process.env,
|
|
33
|
+
});
|
|
34
|
+
return { exitCode: 0, stdout: result.stdout, stderr: result.stderr };
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
const failure = error;
|
|
38
|
+
if (failure.name === "AbortError")
|
|
39
|
+
throw error;
|
|
40
|
+
if (failure.code === "ENOENT") {
|
|
41
|
+
return { exitCode: 127, stderr: `executable_not_found: ${command}` };
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
exitCode: typeof failure.code === "number" ? failure.code : 1,
|
|
45
|
+
stdout: failure.stdout,
|
|
46
|
+
stderr: failure.stderr ?? failure.message,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function quoteWindowsCommandArgument(value) {
|
|
52
|
+
return /^[A-Za-z0-9_./:@=-]+$/u.test(value) ? value : `"${value.replaceAll('"', '""')}"`;
|
|
53
|
+
}
|
|
54
|
+
export class PrePublicationValidator {
|
|
55
|
+
commands;
|
|
56
|
+
constructor(commands = new ProcessPrePublicationCommandRunner()) {
|
|
57
|
+
this.commands = commands;
|
|
58
|
+
}
|
|
59
|
+
async validate(worktreePath, profile, capabilities, emit, signal, execution) {
|
|
60
|
+
const contract = await loadValidationContract(worktreePath);
|
|
61
|
+
if (contract === null) {
|
|
62
|
+
await emit?.(validationEvent("prepublication_validation_legacy_contract", "legacy-provider-validation", `This checkout predates ${contractRelativePath}; Bridge preserved legacy provider validation without source mutation.`));
|
|
63
|
+
return [];
|
|
64
|
+
}
|
|
65
|
+
const scoped = await prepareValidationExecution(execution);
|
|
66
|
+
try {
|
|
67
|
+
const changedPaths = await this.changedPaths(worktreePath, signal, scoped.execution);
|
|
68
|
+
const selected = applicableChecks(contract, profile, changedPaths);
|
|
69
|
+
const completed = [];
|
|
70
|
+
for (const check of selected) {
|
|
71
|
+
if (check.providerOnly) {
|
|
72
|
+
await emit?.(validationEvent("prepublication_validation_provider_only", check.id, `Preserved provider-only validation '${check.id}' for the provider check run.`));
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (check.requiredCapability && !capabilities.has(check.requiredCapability)) {
|
|
76
|
+
throw new Error(`prepublication_capability_unavailable: ${check.id} requires ${check.requiredCapability}; publication is holding until a capable runner is available.`);
|
|
77
|
+
}
|
|
78
|
+
await emit?.(validationEvent("prepublication_validation_started", check.id, `Running pre-publication CI parity check '${check.id}'.`));
|
|
79
|
+
for (const step of check.steps) {
|
|
80
|
+
const result = await this.runStep(check.id, step, worktreePath, signal, scoped.execution);
|
|
81
|
+
if (result.exitCode !== 0) {
|
|
82
|
+
const detail = diagnosticDetail(result);
|
|
83
|
+
await emit?.(validationEvent("prepublication_validation_failed", check.id, `Pre-publication CI parity check '${check.id}' exited ${result.exitCode}${detail ? `: ${detail}` : "."}`));
|
|
84
|
+
throw new Error(`prepublication_validation_failed: ${check.id} exited ${result.exitCode}${detail ? `: ${detail}` : ""}`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
completed.push(check.id);
|
|
88
|
+
await emit?.(validationEvent("prepublication_validation_passed", check.id, `Pre-publication CI parity check '${check.id}' passed.`));
|
|
89
|
+
}
|
|
90
|
+
return completed;
|
|
91
|
+
}
|
|
92
|
+
finally {
|
|
93
|
+
await scoped.cleanup();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
async changedPaths(worktreePath, signal, execution) {
|
|
97
|
+
const baselineRevision = execution?.baselineRevision?.trim();
|
|
98
|
+
const requests = [
|
|
99
|
+
["diff", "--name-only", "HEAD", "--"],
|
|
100
|
+
...(baselineRevision ? [["diff", "--name-only", `${baselineRevision}..HEAD`, "--"]] : []),
|
|
101
|
+
["status", "--porcelain=v1", "--untracked-files=all"],
|
|
102
|
+
];
|
|
103
|
+
const paths = new Set();
|
|
104
|
+
for (const args of requests) {
|
|
105
|
+
const result = await this.runCommand("git", args, worktreePath, signal, execution);
|
|
106
|
+
if (result.exitCode !== 0) {
|
|
107
|
+
throw new Error(`prepublication_validation_failed: unable to inventory changed paths: ${result.stderr ?? result.stdout ?? "git failed"}`);
|
|
108
|
+
}
|
|
109
|
+
for (const line of `${result.stdout ?? ""}`.split(/\r?\n/u).filter(Boolean)) {
|
|
110
|
+
const raw = args[0] === "status" ? line.slice(3).split(" -> ").at(-1) ?? "" : line;
|
|
111
|
+
const normalized = raw.trim().replaceAll("\\", "/");
|
|
112
|
+
if (normalized)
|
|
113
|
+
paths.add(normalized);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return [...paths];
|
|
117
|
+
}
|
|
118
|
+
async runStep(checkId, step, cwd, signal, execution) {
|
|
119
|
+
const invocation = managedAttemptInvocation(checkId, step, execution?.environment);
|
|
120
|
+
const before = await readValidationFiles(cwd, step.assertUnchangedPaths ?? []);
|
|
121
|
+
const result = await this.runCommand(invocation.command, invocation.args, cwd, signal, execution);
|
|
122
|
+
if (result.exitCode === 127 && step.fallbackCommand) {
|
|
123
|
+
const fallback = await this.runCommand(step.fallbackCommand, step.fallbackArgs ?? step.args, cwd, signal, execution);
|
|
124
|
+
return await assertValidationFilesUnchanged(cwd, before, fallback);
|
|
125
|
+
}
|
|
126
|
+
return await assertValidationFilesUnchanged(cwd, before, result);
|
|
127
|
+
}
|
|
128
|
+
async runCommand(command, args, cwd, signal, execution) {
|
|
129
|
+
if (execution?.processRunner) {
|
|
130
|
+
const result = await execution.processRunner.run({
|
|
131
|
+
command,
|
|
132
|
+
args,
|
|
133
|
+
cwd,
|
|
134
|
+
env: execution.environment,
|
|
135
|
+
captureOutput: true,
|
|
136
|
+
}, undefined, signal);
|
|
137
|
+
return { exitCode: result.exitCode, stdout: result.stdout, stderr: result.stderr };
|
|
138
|
+
}
|
|
139
|
+
return await this.commands.run(command, args, cwd, signal, execution?.environment);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function managedAttemptInvocation(checkId, step, environment) {
|
|
143
|
+
const playwrightConfig = environment?.FORGE_PLAYWRIGHT_CONFIG?.trim();
|
|
144
|
+
const attemptOwned = environment?.FORGE_E2E_OWNERSHIP_MODE === "attempt"
|
|
145
|
+
|| Boolean(environment?.FORGE_DISPATCH_ATTEMPT_ID?.trim());
|
|
146
|
+
if (checkId !== "playwright-e2e" || !attemptOwned) {
|
|
147
|
+
return step;
|
|
148
|
+
}
|
|
149
|
+
if (!playwrightConfig) {
|
|
150
|
+
throw new Error("prepublication_capability_unavailable: playwright-e2e requires the Bridge-generated FORGE_PLAYWRIGHT_CONFIG for a managed attempt.");
|
|
151
|
+
}
|
|
152
|
+
return {
|
|
153
|
+
command: "pnpm",
|
|
154
|
+
args: ["--dir", "tests/e2e", "exec", "playwright", "test", "--config", playwrightConfig],
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
function diagnosticDetail(result) {
|
|
158
|
+
return [result.stderr, result.stdout]
|
|
159
|
+
.map(value => value?.trim() ?? "")
|
|
160
|
+
.filter(Boolean)
|
|
161
|
+
.join("\n")
|
|
162
|
+
.slice(-1600);
|
|
163
|
+
}
|
|
164
|
+
async function prepareValidationExecution(execution) {
|
|
165
|
+
if (process.platform !== "win32" || !execution) {
|
|
166
|
+
return { execution, cleanup: async () => undefined };
|
|
167
|
+
}
|
|
168
|
+
const systemDrive = process.env.SystemDrive?.trim() || "C:";
|
|
169
|
+
const configuredRoot = execution.environment?.FORGE_VALIDATION_TEMP_ROOT?.trim();
|
|
170
|
+
const root = configuredRoot || path.win32.join(systemDrive, "ForgeValidationTmp");
|
|
171
|
+
const temporaryRoot = path.win32.join(root, `${process.pid}-${randomUUID().slice(0, 8)}`);
|
|
172
|
+
await fs.mkdir(temporaryRoot, { recursive: true });
|
|
173
|
+
return {
|
|
174
|
+
execution: {
|
|
175
|
+
...execution,
|
|
176
|
+
environment: {
|
|
177
|
+
...execution.environment,
|
|
178
|
+
TEMP: temporaryRoot,
|
|
179
|
+
TMP: temporaryRoot,
|
|
180
|
+
TMPDIR: temporaryRoot,
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
cleanup: async () => {
|
|
184
|
+
await fs.rm(temporaryRoot, { recursive: true, force: true });
|
|
185
|
+
},
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
async function readValidationFiles(cwd, relativePaths) {
|
|
189
|
+
const values = new Map();
|
|
190
|
+
for (const relativePath of relativePaths) {
|
|
191
|
+
values.set(relativePath, await fs.readFile(path.join(cwd, relativePath), "utf8"));
|
|
192
|
+
}
|
|
193
|
+
return values;
|
|
194
|
+
}
|
|
195
|
+
async function assertValidationFilesUnchanged(cwd, before, result) {
|
|
196
|
+
if (result.exitCode !== 0)
|
|
197
|
+
return result;
|
|
198
|
+
for (const [relativePath, original] of before) {
|
|
199
|
+
const current = await fs.readFile(path.join(cwd, relativePath), "utf8");
|
|
200
|
+
if (current !== original) {
|
|
201
|
+
return {
|
|
202
|
+
exitCode: 1,
|
|
203
|
+
stderr: `generated_drift: ${relativePath} changed during validation; regenerate and review it before publication.`,
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return result;
|
|
208
|
+
}
|
|
209
|
+
export function applicableChecks(contract, profile, changedPaths) {
|
|
210
|
+
return contract.checks.filter(check => check.profiles.includes(profile)
|
|
211
|
+
&& changedPaths.some(changedPath => check.changedPathPatterns.some(pattern => new RegExp(pattern, "u").test(changedPath))));
|
|
212
|
+
}
|
|
213
|
+
export async function loadValidationContract(worktreePath) {
|
|
214
|
+
let source;
|
|
215
|
+
try {
|
|
216
|
+
source = await fs.readFile(path.join(worktreePath, contractRelativePath), "utf8");
|
|
217
|
+
}
|
|
218
|
+
catch (error) {
|
|
219
|
+
if (error.code === "ENOENT")
|
|
220
|
+
return null;
|
|
221
|
+
throw error;
|
|
222
|
+
}
|
|
223
|
+
const contract = JSON.parse(source);
|
|
224
|
+
const ids = new Set(contract.checks?.map(check => check.id));
|
|
225
|
+
const contractDigest = createHash("sha256")
|
|
226
|
+
.update(JSON.stringify(canonicalizeJson(contract)))
|
|
227
|
+
.digest("hex");
|
|
228
|
+
if (contract.schemaVersion !== 1
|
|
229
|
+
|| contract.contractId !== "forge-ci-parity-v1"
|
|
230
|
+
|| contractDigest !== approvedContractDigest
|
|
231
|
+
|| requiredCheckIds.size !== ids.size
|
|
232
|
+
|| [...requiredCheckIds].some(id => !ids.has(id))
|
|
233
|
+
|| contract.checks.some(check => !check.id || !Array.isArray(check.steps) || !Array.isArray(check.changedPathPatterns))) {
|
|
234
|
+
throw new Error(`prepublication_contract_invalid: the Forge CI parity contract does not match the approved definition (digest ${contractDigest}, expected ${approvedContractDigest}).`);
|
|
235
|
+
}
|
|
236
|
+
return contract;
|
|
237
|
+
}
|
|
238
|
+
function canonicalizeJson(value) {
|
|
239
|
+
if (Array.isArray(value))
|
|
240
|
+
return value.map(canonicalizeJson);
|
|
241
|
+
if (value !== null && typeof value === "object") {
|
|
242
|
+
const record = value;
|
|
243
|
+
return Object.fromEntries(Object.keys(record).sort().map(key => [key, canonicalizeJson(record[key])]));
|
|
244
|
+
}
|
|
245
|
+
return value;
|
|
246
|
+
}
|
|
247
|
+
function validationEvent(eventType, checkId, content) {
|
|
248
|
+
return { role: "runner", kind: "checkpoint", content, eventType, data: JSON.stringify({ checkId, contractId: "forge-ci-parity-v1" }) };
|
|
249
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { RunOnceDispatchPacket } from "../session.types.js";
|
|
2
|
+
export declare const ciRepairProviderOnlySpecs: readonly ["**/bridge-dispatch.spec.ts", "**/develop-agent-run.spec.ts", "**/runner-availability.spec.ts"];
|
|
3
|
+
export declare const ciRepairLocalPreflightCommands: readonly CiRepairLocalPreflightCommand[];
|
|
4
|
+
export interface CiRepairLocalPreflightCommand {
|
|
5
|
+
readonly id: string;
|
|
6
|
+
readonly cwd: string;
|
|
7
|
+
readonly command: readonly string[];
|
|
8
|
+
readonly coverage: string;
|
|
9
|
+
}
|
|
10
|
+
export interface CiRepairReadinessResult {
|
|
11
|
+
readonly path: string;
|
|
12
|
+
readonly environment: Readonly<Record<string, string>>;
|
|
13
|
+
readonly manifest: Readonly<Record<string, unknown>>;
|
|
14
|
+
}
|
|
15
|
+
export declare function writeCiRepairReadinessManifest(dispatch: RunOnceDispatchPacket, worktreePath: string, specPath: string, runtimeEnvironment: Readonly<Record<string, string>> | undefined): Promise<CiRepairReadinessResult>;
|
|
16
|
+
export declare function assertCiRepairPreflightContract(providerOnlySpecs: readonly string[], localPreflightCommands: readonly CiRepairLocalPreflightCommand[]): void;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { createHash } from "node:crypto";
|
|
4
|
+
export const ciRepairProviderOnlySpecs = [
|
|
5
|
+
"**/bridge-dispatch.spec.ts",
|
|
6
|
+
"**/develop-agent-run.spec.ts",
|
|
7
|
+
"**/runner-availability.spec.ts",
|
|
8
|
+
];
|
|
9
|
+
export const ciRepairLocalPreflightCommands = [];
|
|
10
|
+
export async function writeCiRepairReadinessManifest(dispatch, worktreePath, specPath, runtimeEnvironment) {
|
|
11
|
+
assertCiRepairPreflightContract(ciRepairProviderOnlySpecs, ciRepairLocalPreflightCommands);
|
|
12
|
+
const metadataRoot = path.dirname(specPath);
|
|
13
|
+
const manifestPath = path.join(metadataRoot, "ci-repair.readiness.json");
|
|
14
|
+
const workflowPath = path.join(worktreePath, ".github", "workflows", "ci.yml");
|
|
15
|
+
const browserReady = runtimeEnvironment?.FORGE_PLAYWRIGHT_BROWSER_READY === "true";
|
|
16
|
+
const providerOnlySpecsJson = JSON.stringify(ciRepairProviderOnlySpecs);
|
|
17
|
+
const apiUrl = runtimeEnvironment?.FORGE_E2E_API_URL ?? runtimeEnvironment?.FORGE_API_URL ?? null;
|
|
18
|
+
const webUrl = runtimeEnvironment?.FORGE_E2E_WEB_URL
|
|
19
|
+
?? runtimeEnvironment?.FORGE_WEB_URL
|
|
20
|
+
?? runtimeEnvironment?.FORGE_PLAYWRIGHT_BASE_URL
|
|
21
|
+
?? null;
|
|
22
|
+
const environment = {
|
|
23
|
+
...(runtimeEnvironment ?? {}),
|
|
24
|
+
...(apiUrl ? { FORGE_E2E_API_URL: apiUrl } : {}),
|
|
25
|
+
...(webUrl ? { FORGE_E2E_WEB_URL: webUrl } : {}),
|
|
26
|
+
FORGE_CI_REPAIR_READINESS_PATH: manifestPath,
|
|
27
|
+
FORGE_CI_REPAIR_HANDOFF_PATH: path.join(metadataRoot, "artifacts", "ci-repair.handoff.json"),
|
|
28
|
+
FORGE_CI_REPAIR_PROVIDER_ONLY_SPECS: providerOnlySpecsJson,
|
|
29
|
+
};
|
|
30
|
+
const manifest = {
|
|
31
|
+
schema_version: 1,
|
|
32
|
+
generated_by: "forge-bridge",
|
|
33
|
+
work_item_id: dispatch.workItem.id,
|
|
34
|
+
session_id: dispatch.session.id,
|
|
35
|
+
spec: {
|
|
36
|
+
path: relativePath(worktreePath, specPath),
|
|
37
|
+
ready: await isFile(specPath),
|
|
38
|
+
},
|
|
39
|
+
handoff: {
|
|
40
|
+
path: relativePath(worktreePath, environment.FORGE_CI_REPAIR_HANDOFF_PATH),
|
|
41
|
+
completion_tool: "forge.complete_ci_repair",
|
|
42
|
+
required_before_commit_or_push: true,
|
|
43
|
+
},
|
|
44
|
+
pull_request: {
|
|
45
|
+
provider: dispatch.pullRequest?.provider ?? "unknown",
|
|
46
|
+
number: dispatch.pullRequest?.number ?? null,
|
|
47
|
+
url: dispatch.pullRequest?.url ?? null,
|
|
48
|
+
source_branch: dispatch.pullRequest?.sourceBranch ?? dispatch.cycleRun.baseBranch,
|
|
49
|
+
target_branch: dispatch.pullRequest?.targetBranch ?? dispatch.cycleRun.requestedBase,
|
|
50
|
+
check_state: dispatch.pullRequest?.checkState ?? "unknown",
|
|
51
|
+
required_checks_passed: dispatch.pullRequest?.requiredChecksPassed ?? 0,
|
|
52
|
+
required_checks_total: dispatch.pullRequest?.requiredChecksTotal ?? 0,
|
|
53
|
+
failed_job_discovery: "Inspect provider check runs and record exact job/step in the completion payload.",
|
|
54
|
+
},
|
|
55
|
+
workflow: {
|
|
56
|
+
path: relativePath(worktreePath, workflowPath),
|
|
57
|
+
ready: await isFile(workflowPath),
|
|
58
|
+
requirement: "Record the failed step and every earlier guard/drift step in workflow_validation.",
|
|
59
|
+
},
|
|
60
|
+
runtime: {
|
|
61
|
+
mode: runtimeEnvironment?.FORGE_RUNTIME_MODE ?? "unknown",
|
|
62
|
+
application_runtime_ready: Boolean(apiUrl || webUrl),
|
|
63
|
+
api_url: apiUrl,
|
|
64
|
+
web_url: webUrl,
|
|
65
|
+
playwright_config: runtimeEnvironment?.FORGE_PLAYWRIGHT_CONFIG ?? null,
|
|
66
|
+
playwright_browser_cache: runtimeEnvironment?.PLAYWRIGHT_BROWSERS_PATH ?? null,
|
|
67
|
+
playwright_browser_ready: browserReady,
|
|
68
|
+
playwright_browser_install_command: browserReady
|
|
69
|
+
? null
|
|
70
|
+
: runtimeEnvironment?.FORGE_PLAYWRIGHT_BROWSER_INSTALL_COMMAND ?? "npx playwright install chromium",
|
|
71
|
+
attempt_database_schema: runtimeEnvironment?.FORGE_ATTEMPT_DATABASE_SCHEMA ?? null,
|
|
72
|
+
attempt_database_readiness_path: runtimeEnvironment?.FORGE_ATTEMPT_DATABASE_READINESS_PATH ?? null,
|
|
73
|
+
},
|
|
74
|
+
local_equivalence: {
|
|
75
|
+
default: "supported",
|
|
76
|
+
nested_bridge: "provider_only",
|
|
77
|
+
provider_only_specs: ciRepairProviderOnlySpecs,
|
|
78
|
+
provider_only_specs_fingerprint: `sha256:${createHash("sha256").update(providerOnlySpecsJson).digest("hex")}`,
|
|
79
|
+
local_preflight_commands: ciRepairLocalPreflightCommands,
|
|
80
|
+
reason: "A managed Forge attempt disables its hosted reconciler and cannot exercise specs that require the live Bridge/runner control plane. Those specs remain authoritative in provider CI; attempt-local unit, contract, API, and browser coverage remains supported.",
|
|
81
|
+
policy: "Run every listed local_preflight_command. Treat every provider_only_specs pattern as unavailable in the managed attempt, do not override its exclusion or weaken provider CI, and record the provider check that supplies that proof in workflow_validation.",
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
await fs.mkdir(metadataRoot, { recursive: true });
|
|
85
|
+
await fs.writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`, { encoding: "utf8", mode: 0o600 });
|
|
86
|
+
return { path: manifestPath, environment, manifest };
|
|
87
|
+
}
|
|
88
|
+
export function assertCiRepairPreflightContract(providerOnlySpecs, localPreflightCommands) {
|
|
89
|
+
const providerOnlyFileNames = new Set(providerOnlySpecs.map(fileName));
|
|
90
|
+
for (const preflight of localPreflightCommands) {
|
|
91
|
+
const conflictingArgument = preflight.command.find(argument => providerOnlyFileNames.has(fileName(argument)));
|
|
92
|
+
if (conflictingArgument) {
|
|
93
|
+
throw new Error(`ci_repair_readiness_invalid: local preflight '${preflight.id}' references provider-only spec '${conflictingArgument}'.`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
async function isFile(candidate) {
|
|
98
|
+
try {
|
|
99
|
+
return (await fs.stat(candidate)).isFile();
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function relativePath(worktreePath, candidate) {
|
|
106
|
+
return path.relative(worktreePath, candidate).replaceAll(path.sep, "/");
|
|
107
|
+
}
|
|
108
|
+
function fileName(candidate) {
|
|
109
|
+
return path.posix.basename(candidate.replaceAll("\\", "/"));
|
|
110
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { GitClient } from "../../shared/git/git.js";
|
|
2
|
+
import { type CompletionPhase, type CompletionToolRuntime, type DebugCompletionPhase, type QaCompletionGate } from "../phase-completion.js";
|
|
3
|
+
import type { RunOnceDispatchPacket, RunnerDispatchArtifact, RunnerDispatchSidecar } from "../session.types.js";
|
|
4
|
+
import type { ProviderCliRunContext } from "./provider-cli.types.js";
|
|
5
|
+
export declare function emitDraftGateArtifacts(emit: ProviderCliRunContext["emit"], worktreePath: string, workItemId: string): Promise<void>;
|
|
6
|
+
export declare function emitDecomposeGateArtifacts(emit: ProviderCliRunContext["emit"], worktreePath: string, workItemId: string): Promise<void>;
|
|
7
|
+
export declare function fileExists(filePath: string): Promise<boolean>;
|
|
8
|
+
export declare function summarizeStderr(stderr: string): string;
|
|
9
|
+
export declare function waitForCompletionArtifact(worktreePath: string, workItemId: string, phase: "draft" | "decompose", signal?: AbortSignal): Promise<RunnerDispatchArtifact>;
|
|
10
|
+
export declare function delay(ms: number, signal?: AbortSignal): Promise<void>;
|
|
11
|
+
export declare function cleanupCompletionTools(completionTools: CompletionToolRuntime, emit: ProviderCliRunContext["emit"]): Promise<void>;
|
|
12
|
+
export declare function commitWorktreeChanges(git: GitClient, worktreePath: string, workItemId: string): Promise<{
|
|
13
|
+
readonly commitSha: string;
|
|
14
|
+
readonly changedFiles: readonly string[];
|
|
15
|
+
}>;
|
|
16
|
+
export declare function phaseCompleteEventType(phase: CompletionPhase): string;
|
|
17
|
+
export declare function isDebugCompletionPhaseForProvider(phase: CompletionPhase): phase is DebugCompletionPhase;
|
|
18
|
+
export declare function emitQaArtifactRecorded(emit: ProviderCliRunContext["emit"], worktreePath: string, artifact: RunnerDispatchArtifact): Promise<void>;
|
|
19
|
+
export declare function readQaCompletionArtifactBundle(worktreePath: string, workItemId: string, ownerType?: string | null, ownerId?: string | null): Promise<RunnerDispatchArtifact | null>;
|
|
20
|
+
export declare function hasCompleteQaArtifactBundle(worktreePath: string, workItemId: string, ownerType?: string | null, ownerId?: string | null): Promise<boolean>;
|
|
21
|
+
export declare function enforceQaBrowserLaunchTargetGate(dispatch: RunOnceDispatchPacket, artifact: RunnerDispatchArtifact): Promise<void>;
|
|
22
|
+
export declare function validateQaBundleSidecarReferences(worktreePath: string, workItemId: string, ownerType?: string | null, ownerId?: string | null): Promise<void>;
|
|
23
|
+
export declare function readQaBundleSidecars(worktreePath: string, workItemId: string, ownerType?: string | null, ownerId?: string | null): Promise<RunnerDispatchSidecar[]>;
|
|
24
|
+
export declare function emitQaStructuredEvents(emit: ProviderCliRunContext["emit"], artifact: RunnerDispatchArtifact): Promise<void>;
|
|
25
|
+
interface QaGateArtifactSnapshot {
|
|
26
|
+
readonly gate: QaCompletionGate;
|
|
27
|
+
readonly path: string;
|
|
28
|
+
readonly status: string;
|
|
29
|
+
readonly producedBy?: string;
|
|
30
|
+
readonly contentHash?: string;
|
|
31
|
+
}
|
|
32
|
+
export declare function qaArtifactRootForDispatch(worktreePath: string, workItemId: string, dispatch: RunOnceDispatchPacket): string;
|
|
33
|
+
export declare function readQaGateArtifact(artifactRoot: string, gate: QaCompletionGate): Promise<QaGateArtifactSnapshot | null>;
|
|
34
|
+
export declare function nextQaGate(gate: QaCompletionGate): QaCompletionGate | null;
|
|
35
|
+
export declare function emitQaGateAccepted(emit: ProviderCliRunContext["emit"], worktreePath: string, artifact: QaGateArtifactSnapshot, nextGate: QaCompletionGate | null): Promise<void>;
|
|
36
|
+
export declare class LiveQaArtifactEmitter {
|
|
37
|
+
private readonly worktreePath;
|
|
38
|
+
private readonly workItemId;
|
|
39
|
+
private readonly dispatch;
|
|
40
|
+
private readonly emit;
|
|
41
|
+
private emittedBundle;
|
|
42
|
+
private readonly emittedGates;
|
|
43
|
+
private timer;
|
|
44
|
+
private pending;
|
|
45
|
+
constructor(worktreePath: string, workItemId: string, dispatch: RunOnceDispatchPacket, emit: ProviderCliRunContext["emit"]);
|
|
46
|
+
start(): void;
|
|
47
|
+
stop(): Promise<void>;
|
|
48
|
+
hasEmitted(): boolean;
|
|
49
|
+
private pollQueued;
|
|
50
|
+
private poll;
|
|
51
|
+
private emitAvailableGateEvents;
|
|
52
|
+
}
|
|
53
|
+
export declare class LiveArchitectArtifactEmitter {
|
|
54
|
+
private readonly worktreePath;
|
|
55
|
+
private readonly workItemId;
|
|
56
|
+
private readonly emit;
|
|
57
|
+
private emitted;
|
|
58
|
+
private timer;
|
|
59
|
+
private pending;
|
|
60
|
+
constructor(worktreePath: string, workItemId: string, emit: ProviderCliRunContext["emit"]);
|
|
61
|
+
start(): void;
|
|
62
|
+
stop(): Promise<void>;
|
|
63
|
+
hasEmitted(): boolean;
|
|
64
|
+
private pollQueued;
|
|
65
|
+
private poll;
|
|
66
|
+
}
|
|
67
|
+
export declare function hasCompleteArchitectArtifactBundle(worktreePath: string, workItemId: string): Promise<boolean>;
|
|
68
|
+
export declare function emitArchitectStructuredEvents(emit: ProviderCliRunContext["emit"], worktreePath: string, workItemId: string, artifact: RunnerDispatchArtifact): Promise<void>;
|
|
69
|
+
export declare function readJsonObjectFile(filePath: string): Promise<Record<string, unknown>>;
|
|
70
|
+
export declare function arrayField(source: Record<string, unknown>, key: string): Record<string, unknown>[];
|
|
71
|
+
export declare function stringArrayField(source: Record<string, unknown>, key: string): string[];
|
|
72
|
+
export declare function summarizeQaObject(source: Record<string, unknown>): string;
|
|
73
|
+
export declare function qaArtifactRelativePath(workItemId: string, fileName: string, ownerType?: string | null, ownerId?: string | null): string;
|
|
74
|
+
export declare function emitCompletionArtifactRecorded(emit: ProviderCliRunContext["emit"], worktreePath: string, artifact: RunnerDispatchArtifact): Promise<void>;
|
|
75
|
+
export declare function emitPhaseCompletionEvent(emit: ProviderCliRunContext["emit"], artifact: RunnerDispatchArtifact): Promise<void>;
|
|
76
|
+
export declare function emitPhaseGateEvents(emit: ProviderCliRunContext["emit"], artifact: RunnerDispatchArtifact): Promise<void>;
|
|
77
|
+
export declare function completionPhaseFromArtifact(artifact: RunnerDispatchArtifact): CompletionPhase;
|
|
78
|
+
export declare class LiveCompletionArtifactEmitter {
|
|
79
|
+
private readonly worktreePath;
|
|
80
|
+
private readonly workItemId;
|
|
81
|
+
private readonly emit;
|
|
82
|
+
private readonly phases;
|
|
83
|
+
private readonly emitted;
|
|
84
|
+
private timer;
|
|
85
|
+
private pending;
|
|
86
|
+
constructor(worktreePath: string, workItemId: string, phase: CompletionPhase, developCycle: boolean, debugCycle: boolean, emit: ProviderCliRunContext["emit"]);
|
|
87
|
+
start(): void;
|
|
88
|
+
stop(): Promise<void>;
|
|
89
|
+
hasEmitted(phase: CompletionPhase): boolean;
|
|
90
|
+
private pollQueued;
|
|
91
|
+
private poll;
|
|
92
|
+
}
|
|
93
|
+
export declare function readCompletionArtifactsForRun(worktreePath: string, workItemId: string, phase: CompletionPhase, developCycle: boolean, debugCycle: boolean): Promise<RunnerDispatchArtifact[]>;
|
|
94
|
+
export {};
|