@fitlab-ai/agent-infra 0.9.11 → 0.9.12
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 +6 -6
- package/README.zh-CN.md +6 -6
- package/dist/bin/internal-cli.js +5 -0
- package/dist/lib/agent-clients/adapters/codex-lifecycle/build-identity.js +71 -10
- package/dist/lib/defaults.json +4 -0
- package/dist/lib/git/workflow.js +43 -1
- package/dist/lib/init.js +1 -0
- package/dist/lib/internal/git-workflow.js +8 -1
- package/dist/lib/internal/platform-pr.js +8 -2
- package/dist/lib/internal/task-delivery.js +59 -0
- package/dist/lib/platform/github-client.js +7 -1
- package/dist/lib/platform/pr-checks.js +8 -5
- package/dist/lib/platform/pr-summary.js +12 -8
- package/dist/lib/platform/pull-requests.js +393 -91
- package/dist/lib/platform/verification-required.js +13 -2
- package/dist/lib/platform/verification-sync.js +9 -4
- package/dist/lib/pr-review/evidence-grading.js +12 -4
- package/dist/lib/sandbox/config.js +5 -0
- package/dist/lib/sandbox/control/lifecycle.js +29 -7
- package/dist/lib/server/process-state.js +2 -2
- package/dist/lib/task/artifact-lifecycle.js +2 -2
- package/dist/lib/task/commit-intent.js +100 -0
- package/dist/lib/task/commit-operation.js +195 -101
- package/dist/lib/task/create.js +33 -7
- package/dist/lib/task/decision-details.js +3 -48
- package/dist/lib/task/delivery-target.js +97 -0
- package/dist/lib/task/delivery.js +153 -0
- package/dist/lib/task/human-override.js +5 -2
- package/dist/lib/task/lifecycle.js +106 -9
- package/dist/lib/task/orchestration.js +55 -62
- package/dist/lib/task/pr-delivery-fact.js +182 -0
- package/dist/lib/task/review-finalization.js +4 -8
- package/dist/lib/task/review-fingerprint.js +8 -0
- package/dist/lib/task/verification-engine.js +48 -24
- package/dist/lib/task/verification-review.js +1 -1
- package/dist/lib/update.js +9 -0
- package/dist/lifecycle-build-manifest.json +3 -3
- package/lib/agent-clients/adapters/codex-lifecycle/build-identity.ts +105 -10
- package/lib/agent-clients/adapters/codex-lifecycle/manifest-files.json +12 -1
- package/lib/defaults.json +4 -0
- package/lib/git/workflow.ts +38 -1
- package/lib/init.ts +3 -0
- package/lib/internal/git-workflow.ts +7 -1
- package/lib/internal/platform-pr.ts +8 -1
- package/lib/internal/task-delivery.ts +53 -0
- package/lib/platform/github-client.ts +8 -1
- package/lib/platform/pr-checks.ts +7 -5
- package/lib/platform/pr-summary.ts +10 -7
- package/lib/platform/pull-requests.ts +425 -87
- package/lib/platform/verification-required.ts +12 -2
- package/lib/platform/verification-sync.ts +9 -4
- package/lib/pr-review/evidence-grading.ts +7 -4
- package/lib/sandbox/config.ts +7 -0
- package/lib/sandbox/control/lifecycle.ts +30 -8
- package/lib/server/process-state.ts +2 -2
- package/lib/task/artifact-lifecycle.ts +2 -2
- package/lib/task/commit-intent.ts +137 -0
- package/lib/task/commit-operation.ts +174 -87
- package/lib/task/create.ts +34 -9
- package/lib/task/decision-details.ts +2 -62
- package/lib/task/delivery-target.ts +130 -0
- package/lib/task/delivery.ts +160 -0
- package/lib/task/human-override.ts +5 -2
- package/lib/task/lifecycle.ts +93 -4
- package/lib/task/orchestration.ts +62 -65
- package/lib/task/pr-delivery-fact.ts +254 -0
- package/lib/task/review-finalization.ts +4 -14
- package/lib/task/review-fingerprint.ts +10 -0
- package/lib/task/verification-engine.ts +45 -28
- package/lib/task/verification-review.ts +2 -0
- package/lib/update.ts +10 -0
- package/package.json +1 -1
- package/templates/.agents/rules/README.en.md +4 -2
- package/templates/.agents/rules/README.zh-CN.md +4 -2
- package/templates/.agents/rules/create-issue.en.md +11 -2
- package/templates/.agents/rules/create-issue.zh-CN.md +24 -2
- package/templates/.agents/rules/issue-pr-commands.en.md +4 -17
- package/templates/.agents/rules/issue-sync.en.md +26 -5
- package/templates/.agents/rules/issue-sync.zh-CN.md +62 -5
- package/templates/.agents/rules/label-milestone-setup.en.md +15 -2
- package/templates/.agents/rules/label-milestone-setup.zh-CN.md +15 -2
- package/templates/.agents/rules/local-artifact-repair.en.md +46 -0
- package/templates/.agents/rules/local-artifact-repair.zh-CN.md +46 -0
- package/templates/.agents/rules/milestone-inference.en.md +12 -2
- package/templates/.agents/rules/milestone-inference.zh-CN.md +25 -3
- package/templates/.agents/rules/pr-sync.en.md +22 -13
- package/templates/.agents/rules/pr-sync.zh-CN.md +22 -1
- package/templates/.agents/rules/release-commands.en.md +42 -3
- package/templates/.agents/rules/release-commands.zh-CN.md +42 -3
- package/templates/.agents/rules/security-alerts.en.md +17 -2
- package/templates/.agents/rules/security-alerts.zh-CN.md +17 -2
- package/templates/.agents/rules/sync-content-generation.en.md +8 -0
- package/templates/.agents/rules/sync-content-generation.zh-CN.md +8 -0
- package/templates/.agents/rules/task-management.en.md +1 -1
- package/templates/.agents/rules/task-management.zh-CN.md +1 -1
- package/templates/.agents/scripts/security-alerts.github.sh +151 -0
- package/templates/.agents/scripts/security-alerts.sh +31 -0
- package/templates/.agents/skills/analyze-task/SKILL.en.md +1 -0
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +1 -0
- package/templates/.agents/skills/close-codescan/SKILL.en.md +2 -2
- package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/close-dependabot/SKILL.en.md +2 -2
- package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/code-task/SKILL.en.md +5 -2
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +6 -3
- package/templates/.agents/skills/commit/SKILL.en.md +3 -3
- package/templates/.agents/skills/commit/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/commit/config/verify.json +1 -1
- package/templates/.agents/skills/commit/reference/commit-orchestration.en.md +3 -3
- package/templates/.agents/skills/commit/reference/commit-orchestration.zh-CN.md +3 -3
- package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +1 -1
- package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +1 -1
- package/templates/.agents/skills/commit/reference/task-status-update.en.md +2 -2
- package/templates/.agents/skills/commit/reference/task-status-update.zh-CN.md +2 -2
- package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +2 -1
- package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +2 -1
- package/templates/.agents/skills/complete-manual-validation/config/verify.en.json +1 -1
- package/templates/.agents/skills/complete-manual-validation/config/verify.zh-CN.json +1 -1
- package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +1 -1
- package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +1 -1
- package/templates/.agents/skills/complete-task/SKILL.en.md +10 -10
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +10 -10
- package/templates/.agents/skills/complete-task/reference/external-delivery.en.md +2 -2
- package/templates/.agents/skills/complete-task/reference/external-delivery.zh-CN.md +2 -2
- package/templates/.agents/skills/create-pr/SKILL.en.md +4 -4
- package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/create-task/SKILL.en.md +1 -0
- package/templates/.agents/skills/create-task/SKILL.zh-CN.md +1 -0
- package/templates/.agents/skills/import-codescan/SKILL.en.md +1 -1
- package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/import-dependabot/SKILL.en.md +1 -1
- package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/init-labels/SKILL.en.md +9 -10
- package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +9 -10
- package/templates/.agents/skills/init-labels/scripts/init-labels.github.sh +57 -1
- package/templates/.agents/skills/init-labels/scripts/init-labels.sh +27 -1
- package/templates/.agents/skills/init-milestones/SKILL.en.md +3 -5
- package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +3 -5
- package/templates/.agents/skills/plan-task/SKILL.en.md +1 -0
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +1 -0
- package/templates/.agents/skills/review-analysis/SKILL.en.md +4 -3
- package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +4 -3
- package/templates/.agents/skills/review-analysis/reference/output-templates.en.md +18 -0
- package/templates/.agents/skills/review-analysis/reference/output-templates.zh-CN.md +18 -0
- package/templates/.agents/skills/review-code/SKILL.en.md +7 -6
- package/templates/.agents/skills/review-code/SKILL.zh-CN.md +7 -6
- package/templates/.agents/skills/review-code/reference/output-templates.en.md +19 -1
- package/templates/.agents/skills/review-code/reference/output-templates.zh-CN.md +19 -1
- package/templates/.agents/skills/review-code/reference/report-template.en.md +4 -2
- package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +4 -2
- package/templates/.agents/skills/review-plan/SKILL.en.md +4 -3
- package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +4 -3
- package/templates/.agents/skills/review-plan/reference/output-templates.en.md +18 -0
- package/templates/.agents/skills/review-plan/reference/output-templates.zh-CN.md +18 -0
- package/templates/.agents/skills/review-pr/SKILL.en.md +1 -0
- package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +1 -0
- package/templates/.agents/skills/review-pr/reference/evidence-grading.en.md +2 -2
- package/templates/.agents/skills/review-pr/reference/evidence-grading.zh-CN.md +2 -2
- package/templates/.agents/skills/run-manual-validation/SKILL.en.md +1 -0
- package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +1 -0
- package/templates/.agents/skills/run-task/SKILL.en.md +1 -1
- package/templates/.agents/skills/run-task/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +4 -0
- package/templates/.agents/skills/watch-pr/SKILL.en.md +4 -4
- package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +4 -4
- package/templates/.agents/templates/task.en.md +5 -1
- package/templates/.agents/templates/task.zh-CN.md +5 -1
- package/templates/.agents/workflows/bug-fix.en.yaml +9 -8
- package/templates/.agents/workflows/bug-fix.zh-CN.yaml +9 -8
- package/templates/.agents/workflows/feature-development.en.yaml +9 -8
- package/templates/.agents/workflows/feature-development.zh-CN.yaml +9 -8
- package/templates/.agents/workflows/refactoring.en.yaml +9 -8
- package/templates/.agents/workflows/refactoring.zh-CN.yaml +9 -8
- package/templates/.agents/rules/create-issue.github.en.md +0 -14
- package/templates/.agents/rules/create-issue.github.zh-CN.md +0 -27
- package/templates/.agents/rules/issue-pr-commands.github.en.md +0 -34
- package/templates/.agents/rules/issue-pr-commands.github.zh-CN.md +0 -49
- package/templates/.agents/rules/issue-sync.github.en.md +0 -40
- package/templates/.agents/rules/issue-sync.github.zh-CN.md +0 -76
- package/templates/.agents/rules/label-milestone-setup.github.en.md +0 -60
- package/templates/.agents/rules/label-milestone-setup.github.zh-CN.md +0 -60
- package/templates/.agents/rules/milestone-inference.github.en.md +0 -15
- package/templates/.agents/rules/milestone-inference.github.zh-CN.md +0 -27
- package/templates/.agents/rules/pr-checks-commands.github.en.md +0 -18
- package/templates/.agents/rules/pr-checks-commands.github.zh-CN.md +0 -34
- package/templates/.agents/rules/pr-sync.github.en.md +0 -43
- package/templates/.agents/rules/pr-sync.github.zh-CN.md +0 -69
- package/templates/.agents/rules/release-commands.github.en.md +0 -44
- package/templates/.agents/rules/release-commands.github.zh-CN.md +0 -44
- package/templates/.agents/rules/security-alerts.github.en.md +0 -43
- package/templates/.agents/rules/security-alerts.github.zh-CN.md +0 -43
- /package/templates/.agents/rules/{issue-fields.github.en.md → issue-fields.en.md} +0 -0
- /package/templates/.agents/rules/{issue-fields.github.zh-CN.md → issue-fields.zh-CN.md} +0 -0
package/lib/defaults.json
CHANGED
package/lib/git/workflow.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { spawnSync } from 'node:child_process';
|
|
2
2
|
import fs from 'node:fs';
|
|
3
|
+
import os from 'node:os';
|
|
3
4
|
import path from 'node:path';
|
|
4
5
|
|
|
5
6
|
type CommandResult = { status: number | null; stdout: string; stderr: string };
|
|
@@ -105,6 +106,42 @@ function commitExplicitPaths(input: { cwd: string; paths: readonly string[]; mes
|
|
|
105
106
|
return { status: 'applied' as const, changed: true, snapshot: after.snapshot, operations: [{ name: 'stage', status: 'applied' as const }, { name: 'commit', status: 'applied' as const }], error: null };
|
|
106
107
|
}
|
|
107
108
|
|
|
109
|
+
function previewCommitTree(input: { cwd: string; paths: readonly string[]; expectedHead: string }) {
|
|
110
|
+
const invalid = validatePaths(input.paths);
|
|
111
|
+
if (invalid) return { status: 'failed' as const, tree: null, error: { code: 'GIT_COMMIT_INPUT_INVALID', message: invalid } };
|
|
112
|
+
const before = inspectGitWorkflow(input.cwd);
|
|
113
|
+
if (!before.snapshot) return { status: 'failed' as const, tree: null, error: { code: 'GIT_INSPECT_FAILED', message: 'Unable to inspect Git repository' } };
|
|
114
|
+
if (before.snapshot.head !== input.expectedHead) {
|
|
115
|
+
return { status: 'failed' as const, tree: null, error: { code: 'GIT_HEAD_MISMATCH', message: `Expected HEAD ${input.expectedHead}, received ${before.snapshot.head}` } };
|
|
116
|
+
}
|
|
117
|
+
const selected = new Set(input.paths);
|
|
118
|
+
const unrelatedStaged = before.snapshot.staged.filter((candidate) => !selected.has(candidate));
|
|
119
|
+
if (unrelatedStaged.length > 0) {
|
|
120
|
+
return { status: 'failed' as const, tree: null, error: { code: 'GIT_STAGED_SCOPE_MISMATCH', message: `Unrelated staged paths: ${unrelatedStaged.join(', ')}` } };
|
|
121
|
+
}
|
|
122
|
+
const temporaryDirectory = fs.mkdtempSync(path.join(os.tmpdir(), 'agent-infra-preview-index-'));
|
|
123
|
+
const indexFile = path.join(temporaryDirectory, 'index');
|
|
124
|
+
const temporaryRunner: GitRunner = (args, cwd) => {
|
|
125
|
+
const result = spawnSync('git', [...args], {
|
|
126
|
+
cwd,
|
|
127
|
+
env: { ...process.env, GIT_INDEX_FILE: indexFile },
|
|
128
|
+
encoding: 'utf8'
|
|
129
|
+
});
|
|
130
|
+
return { status: result.status, stdout: result.stdout ?? '', stderr: result.stderr ?? '' };
|
|
131
|
+
};
|
|
132
|
+
try {
|
|
133
|
+
const read = run(temporaryRunner, input.cwd, ['read-tree', input.expectedHead]);
|
|
134
|
+
if (read.status !== 0) return { status: 'failed' as const, tree: null, error: { code: 'GIT_PREVIEW_FAILED', message: read.stderr.trim() || 'Unable to prepare a temporary Git index' } };
|
|
135
|
+
const stage = run(temporaryRunner, input.cwd, ['add', '-A', '--', ...input.paths]);
|
|
136
|
+
if (stage.status !== 0) return { status: 'failed' as const, tree: null, error: { code: 'GIT_PREVIEW_FAILED', message: stage.stderr.trim() || 'Unable to stage the requested paths in a temporary index' } };
|
|
137
|
+
const tree = value(temporaryRunner, input.cwd, ['write-tree']);
|
|
138
|
+
if (!tree) return { status: 'failed' as const, tree: null, error: { code: 'GIT_PREVIEW_FAILED', message: 'Unable to write the temporary Git tree' } };
|
|
139
|
+
return { status: 'planned' as const, tree, error: null };
|
|
140
|
+
} finally {
|
|
141
|
+
fs.rmSync(temporaryDirectory, { recursive: true, force: true });
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
108
145
|
function pushGitRefs(input: { cwd: string; remote: string; refs: readonly string[]; expectedSha?: string }, runner: GitRunner = defaultRunner) {
|
|
109
146
|
if (!input.remote || input.refs.length === 0) return { status: 'failed' as const, changed: false, snapshot: inspectGitWorkflow(input.cwd, runner).snapshot, operations: [], error: { code: 'GIT_PUSH_INPUT_INVALID', message: 'Remote and refs are required' } };
|
|
110
147
|
const operations: GitOperation[] = [];
|
|
@@ -192,5 +229,5 @@ function pushRebasedBranch(input: PushRebasedInput, runner: GitRunner = defaultR
|
|
|
192
229
|
return { status: 'applied' as const, changed: true, snapshot: inspectGitWorkflow(input.cwd, runner).snapshot, operations: [{ name: 'push-rebased', status: 'applied' as const, ref: input.branch }], error: null };
|
|
193
230
|
}
|
|
194
231
|
|
|
195
|
-
export { commitExplicitPaths, inspectGitWorkflow, pushGitRefs, pushRebasedBranch };
|
|
232
|
+
export { commitExplicitPaths, inspectGitWorkflow, previewCommitTree, pushGitRefs, pushRebasedBranch };
|
|
196
233
|
export type { CommandResult, GitRunner, PushRebasedInput };
|
package/lib/init.ts
CHANGED
|
@@ -32,6 +32,7 @@ type Defaults = {
|
|
|
32
32
|
files: FileRegistry;
|
|
33
33
|
sandbox: Record<string, unknown>;
|
|
34
34
|
task: { shortIdLength: number };
|
|
35
|
+
delivery: { remote: string; baseRef: string };
|
|
35
36
|
labels: Record<string, unknown>;
|
|
36
37
|
};
|
|
37
38
|
|
|
@@ -43,6 +44,7 @@ type AgentConfig = {
|
|
|
43
44
|
templateVersion: string;
|
|
44
45
|
sandbox: Record<string, unknown>;
|
|
45
46
|
task: { shortIdLength: number };
|
|
47
|
+
delivery: { remote: string; baseRef: string };
|
|
46
48
|
labels: Record<string, unknown>;
|
|
47
49
|
files: FileRegistry;
|
|
48
50
|
agentClients: ReturnType<typeof serializeAgentClients>;
|
|
@@ -244,6 +246,7 @@ async function cmdInit(): Promise<void> {
|
|
|
244
246
|
templateVersion: VERSION,
|
|
245
247
|
sandbox: structuredClone(defaults.sandbox),
|
|
246
248
|
task: structuredClone(defaults.task),
|
|
249
|
+
delivery: structuredClone(defaults.delivery),
|
|
247
250
|
labels: structuredClone(defaults.labels),
|
|
248
251
|
files: { managed: [], merged: [], ejected: [] },
|
|
249
252
|
agentClients: serializeAgentClients(defaultState)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
|
-
import { inspectGitWorkflow, pushRebasedBranch } from '../git/workflow.ts';
|
|
2
|
+
import { inspectGitWorkflow, previewCommitTree, pushRebasedBranch } from '../git/workflow.ts';
|
|
3
3
|
import { compareReviewTrees, snapshotReview } from '../git/review-snapshot.ts';
|
|
4
4
|
import { resolvePostReviewGlobs } from '../task/review-fingerprint.ts';
|
|
5
5
|
import { executeCommitOperation } from '../task/commit-operation.ts';
|
|
@@ -26,6 +26,12 @@ function gitWorkflow(args: string[] = []): void {
|
|
|
26
26
|
const inputIndex = rest.indexOf('--input');
|
|
27
27
|
const input = inputIndex >= 0 && rest[inputIndex + 1] ? JSON.parse(fs.readFileSync(rest[inputIndex + 1]!, 'utf8')) : null;
|
|
28
28
|
result = input ? pushRebasedBranch({ cwd: cwd ?? process.cwd(), ...input }) : { status: 'failed', changed: false, error: { code: 'GIT_INPUT_REQUIRED', message: '--input JSON file is required' } };
|
|
29
|
+
} else if (action === 'preview-tree') {
|
|
30
|
+
const inputIndex = rest.indexOf('--input');
|
|
31
|
+
const input = inputIndex >= 0 && rest[inputIndex + 1] ? JSON.parse(fs.readFileSync(rest[inputIndex + 1]!, 'utf8')) : null;
|
|
32
|
+
result = input
|
|
33
|
+
? previewCommitTree({ cwd: cwd ?? process.cwd(), paths: input.paths, expectedHead: input.expectedHead })
|
|
34
|
+
: { status: 'failed', changed: false, error: { code: 'GIT_INPUT_REQUIRED', message: '--input JSON file is required' } };
|
|
29
35
|
} else if (action === 'snapshot' || action === 'compare-trees') {
|
|
30
36
|
const inputIndex = rest.indexOf('--input');
|
|
31
37
|
const input = inputIndex >= 0 && rest[inputIndex + 1] ? JSON.parse(fs.readFileSync(rest[inputIndex + 1]!, 'utf8')) : null;
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
createPlatformPullRequest,
|
|
8
8
|
inspectPlatformPullRequest,
|
|
9
9
|
resolveExternalPullRequest,
|
|
10
|
+
skipPlatformPullRequestFact,
|
|
10
11
|
syncPlatformPullRequest
|
|
11
12
|
} from '../platform/pull-requests.ts';
|
|
12
13
|
import type { PullRequestResult } from '../platform/pull-requests.ts';
|
|
@@ -17,6 +18,7 @@ const USAGE = `Usage: agent-infra-internal platform-pr inspect <task-ref> [--cwd
|
|
|
17
18
|
agent-infra-internal platform-pr resolve-external <task-ref> --agent <agent> [--pr <N>] [--dry-run] [--cwd <path>]
|
|
18
19
|
agent-infra-internal platform-pr create <task-ref> --agent <agent> --base <branch> --head <branch> --title-file <path|-> --body-file <path|-> [--draft] [--dry-run] [--cwd <path>]
|
|
19
20
|
agent-infra-internal platform-pr bind <task-ref> --pr <N> --agent <agent> [--dry-run] [--cwd <path>]
|
|
21
|
+
agent-infra-internal platform-pr skip <task-ref> --agent <agent> [--dry-run] [--cwd <path>]
|
|
20
22
|
agent-infra-internal platform-pr sync <task-ref> --agent <agent> [--metadata] [--closing-issue] --result <pr_created|pr_reused|no_op> [--dry-run] [--cwd <path>]
|
|
21
23
|
agent-infra-internal platform-pr summary-context <task-ref> [--cwd <path>]
|
|
22
24
|
agent-infra-internal platform-pr summary-sync <task-ref> --agent <agent> --body-file <path|-> --result <pr_created|pr_reused|no_op> [--dry-run] [--cwd <path>]
|
|
@@ -64,7 +66,7 @@ function readFile(value: string, cwd: string): string {
|
|
|
64
66
|
function platformPr(args: string[] = []): void {
|
|
65
67
|
if (args[0] === '--help' || args[0] === '-h') { process.stdout.write(USAGE); return; }
|
|
66
68
|
const operation = args[0];
|
|
67
|
-
if (!operation || !['inspect', 'resolve-external', 'create', 'bind', 'sync', 'summary-context', 'summary-sync'].includes(operation)) { fail('a valid operation is required'); return; }
|
|
69
|
+
if (!operation || !['inspect', 'resolve-external', 'create', 'bind', 'skip', 'sync', 'summary-context', 'summary-sync'].includes(operation)) { fail('a valid operation is required'); return; }
|
|
68
70
|
const taskRef = args[1];
|
|
69
71
|
if (!taskRef || taskRef.startsWith('--')) { fail(`${operation} requires a task ref`); return; }
|
|
70
72
|
const parsed = parse(args, 2);
|
|
@@ -76,6 +78,7 @@ function platformPr(args: string[] = []): void {
|
|
|
76
78
|
'resolve-external': ['cwd', 'agent', 'pr', 'dryRun'],
|
|
77
79
|
create: ['cwd', 'agent', 'base', 'head', 'titleFile', 'bodyFile', 'draft', 'dryRun'],
|
|
78
80
|
bind: ['cwd', 'agent', 'pr', 'dryRun'],
|
|
81
|
+
skip: ['cwd', 'agent', 'dryRun'],
|
|
79
82
|
sync: ['cwd', 'agent', 'metadata', 'closingIssue', 'result', 'dryRun'],
|
|
80
83
|
'summary-context': ['cwd'],
|
|
81
84
|
'summary-sync': ['cwd', 'agent', 'bodyFile', 'result', 'dryRun']
|
|
@@ -88,6 +91,10 @@ function platformPr(args: string[] = []): void {
|
|
|
88
91
|
const agent = normalizeAgentToken(values.agent);
|
|
89
92
|
if (!agent) { fail(`invalid --agent '${values.agent}': ${AGENT_USAGE_HINT}`); return; }
|
|
90
93
|
values.agent = agent;
|
|
94
|
+
if (operation === 'skip') {
|
|
95
|
+
finish(skipPlatformPullRequestFact(taskRef, { cwd, agent, dryRun: values.dryRun === true }));
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
91
98
|
const primaryResult = values.result === undefined ? undefined : values.result;
|
|
92
99
|
if (primaryResult !== undefined && !['pr_created', 'pr_reused', 'no_op'].includes(primaryResult as string)) {
|
|
93
100
|
fail('--result must be pr_created, pr_reused, or no_op');
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
|
|
3
|
+
import { normalizeAgentToken, AGENT_USAGE_HINT } from '../agent-clients/tokens.ts';
|
|
4
|
+
import { deliverTaskBranch } from '../task/delivery.ts';
|
|
5
|
+
|
|
6
|
+
const USAGE = `Usage: agent-infra-internal task-delivery <task-ref> deliver --agent <agent> [--remote <name>] [--base <branch>] [--dry-run] [--cwd <path>]\n`;
|
|
7
|
+
|
|
8
|
+
function taskDelivery(args: string[] = []): void {
|
|
9
|
+
const taskRef = args[0];
|
|
10
|
+
const operation = args[1];
|
|
11
|
+
if (!taskRef || operation !== 'deliver') {
|
|
12
|
+
process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'DELIVERY_PAYLOAD_INVALID', message: 'task ref and deliver operation are required' } })}\n`);
|
|
13
|
+
process.stderr.write(USAGE);
|
|
14
|
+
process.exitCode = 1;
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
let agent = '';
|
|
18
|
+
let remote: string | undefined;
|
|
19
|
+
let baseRef: string | undefined;
|
|
20
|
+
let cwd = process.cwd();
|
|
21
|
+
let dryRun = false;
|
|
22
|
+
for (let index = 2; index < args.length; index += 1) {
|
|
23
|
+
const flag = args[index];
|
|
24
|
+
if (flag === '--dry-run') { dryRun = true; continue; }
|
|
25
|
+
const value = args[++index];
|
|
26
|
+
if (value === undefined || value.startsWith('--')) {
|
|
27
|
+
process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'DELIVERY_PAYLOAD_INVALID', message: `${flag} requires a value` } })}\n`);
|
|
28
|
+
process.exitCode = 1;
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (flag === '--agent') agent = value;
|
|
32
|
+
else if (flag === '--remote') remote = value;
|
|
33
|
+
else if (flag === '--base') baseRef = value;
|
|
34
|
+
else if (flag === '--cwd') cwd = path.resolve(value);
|
|
35
|
+
else {
|
|
36
|
+
process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'DELIVERY_PAYLOAD_INVALID', message: `unknown option '${flag}'` } })}\n`);
|
|
37
|
+
process.exitCode = 1;
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const normalized = normalizeAgentToken(agent);
|
|
42
|
+
if (!normalized) {
|
|
43
|
+
process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'DELIVERY_PAYLOAD_INVALID', message: `invalid --agent '${agent}': ${AGENT_USAGE_HINT}` } })}\n`);
|
|
44
|
+
process.exitCode = 1;
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const result = deliverTaskBranch(taskRef, { repoRoot: cwd, agent: normalized, remote, baseRef, dryRun });
|
|
48
|
+
process.stdout.write(`${JSON.stringify(result)}\n`);
|
|
49
|
+
if (result.status === 'failed') process.exitCode = 1;
|
|
50
|
+
if (result.status === 'blocked') process.exitCode = 2;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export { taskDelivery };
|
|
@@ -37,8 +37,15 @@ const MINIMUM_GITHUB_CLI_VERSION = '2.72.0';
|
|
|
37
37
|
const GITHUB_CLI_MAX_BUFFER = 64 * 1024 * 1024;
|
|
38
38
|
const ERROR_DETAIL_LIMIT = 4096;
|
|
39
39
|
|
|
40
|
+
function redactDiagnostic(value: string): string {
|
|
41
|
+
return value
|
|
42
|
+
.replace(/\b(?:gh[pousr]_[A-Za-z0-9_]+|github_pat_[A-Za-z0-9_]+)\b/g, '[REDACTED_TOKEN]')
|
|
43
|
+
.replace(/\b(bearer|token)\s+[A-Za-z0-9._~+\/-]+/gi, '$1 [REDACTED_TOKEN]')
|
|
44
|
+
.replace(/([?&](?:access_token|token|client_secret|password)=)[^&\s]+/gi, '$1[REDACTED]');
|
|
45
|
+
}
|
|
46
|
+
|
|
40
47
|
function boundedFailureDetail(result: RunResult): string {
|
|
41
|
-
const diagnostic = `${result.stderr}\n${result.error?.message || ''}
|
|
48
|
+
const diagnostic = redactDiagnostic(`${result.stderr}\n${result.error?.message || ''}`).trim() || redactDiagnostic(result.stdout.trim());
|
|
42
49
|
return diagnostic.length <= ERROR_DETAIL_LIMIT
|
|
43
50
|
? diagnostic
|
|
44
51
|
: `${diagnostic.slice(0, ERROR_DETAIL_LIMIT)}… [truncated]`;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { parseTypedTaskFrontmatter } from '../task/frontmatter.ts';
|
|
4
4
|
import { resolveTaskRef } from '../task/resolve-ref.ts';
|
|
5
5
|
import {
|
|
6
6
|
inspectPlatformRequiredChecks,
|
|
@@ -14,6 +14,7 @@ import { inspectPlatformPullRequest } from './pull-requests.ts';
|
|
|
14
14
|
import { platformResult } from './types.ts';
|
|
15
15
|
import type { PlatformResult } from './types.ts';
|
|
16
16
|
import type { PullRequestSnapshot } from './pull-requests.ts';
|
|
17
|
+
import { readPrDeliveryFact } from '../task/pr-delivery-fact.ts';
|
|
17
18
|
|
|
18
19
|
type CheckBucket = 'pass' | 'fail' | 'pending' | 'cancel';
|
|
19
20
|
type CheckState = 'passed' | 'failed' | 'pending' | 'timed-out' | 'cancelled' | 'no-required';
|
|
@@ -121,10 +122,11 @@ registerPlatformCapabilities('github', {
|
|
|
121
122
|
function resolvedTask(taskRef: string, options: InspectionOptions) {
|
|
122
123
|
const resolved = resolveTaskRef(taskRef, options.cwd ? { repoRoot: options.cwd } : {});
|
|
123
124
|
if (!resolved.ok) return { ok: false as const, output: checksResult('failed', { error: { code: resolved.code, message: resolved.message, retryable: false } }) };
|
|
124
|
-
const frontmatter =
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
125
|
+
const frontmatter = parseTypedTaskFrontmatter(fs.readFileSync(resolved.taskMdPath, 'utf8'));
|
|
126
|
+
const fact = readPrDeliveryFact(frontmatter);
|
|
127
|
+
if (fact.status === 'invalid') return { ok: false as const, output: checksResult('failed', { error: { code: 'PR_DELIVERY_FACT_INVALID', message: fact.error.message, retryable: false } }) };
|
|
128
|
+
const prNumber = fact.status === 'valid' && fact.fact.state === 'bound' ? fact.fact.identity.number : null;
|
|
129
|
+
if (!prNumber) return { ok: false as const, output: checksResult('failed', { error: { code: fact.status === 'missing' ? 'PR_DELIVERY_FACT_MISSING' : 'PR_NOT_LINKED', message: 'Task has no verified bound pull request', retryable: false } }) };
|
|
128
130
|
const client = (options.client as GitHubClient | undefined) || createGitHubClient();
|
|
129
131
|
const context = resolvePlatformContext({ cwd: resolved.repoRoot, client });
|
|
130
132
|
if (!context.platform.repository || !['no-op', 'degraded'].includes(context.status)) return { ok: false as const, output: checksResult(context.status, { platform: context.platform, capabilities: context.capabilities, error: context.error }) };
|
|
@@ -2,7 +2,7 @@ import fs from 'node:fs';
|
|
|
2
2
|
import { execFileSync } from 'node:child_process';
|
|
3
3
|
|
|
4
4
|
import { enumerateArtifacts } from '../task/artifacts.ts';
|
|
5
|
-
import {
|
|
5
|
+
import { parseTypedTaskFrontmatter } from '../task/frontmatter.ts';
|
|
6
6
|
import { renderHumanOverrideAudit } from '../task/human-override.ts';
|
|
7
7
|
import { resolveTaskRef } from '../task/resolve-ref.ts';
|
|
8
8
|
import { resolvePlatformContext } from './context.ts';
|
|
@@ -12,6 +12,7 @@ import { listRemoteComments, normalizeCommentContent, writeComment } from './iss
|
|
|
12
12
|
import { platformResult } from './types.ts';
|
|
13
13
|
import type { PlatformResult } from './types.ts';
|
|
14
14
|
import type { OperationWarning } from '../task/operation-outcome.ts';
|
|
15
|
+
import { readPrDeliveryFact } from '../task/pr-delivery-fact.ts';
|
|
15
16
|
|
|
16
17
|
type SummaryComment = { id: number; body: string };
|
|
17
18
|
type SummaryContextResult = PlatformResult & {
|
|
@@ -67,9 +68,9 @@ function canonicalArtifacts(taskDir: string) {
|
|
|
67
68
|
function summaryContext(taskRef: string, options: { cwd?: string; client?: GitHubClient } = {}): SummaryContextResult {
|
|
68
69
|
const resolved = resolveTaskRef(taskRef, options.cwd ? { repoRoot: options.cwd } : {});
|
|
69
70
|
if (!resolved.ok) return { ...platformResult('failed', { error: { code: resolved.code, message: resolved.message, retryable: false } }), task: { id: resolved.taskId, prNumber: null }, artifacts: [] };
|
|
70
|
-
const frontmatter =
|
|
71
|
-
const
|
|
72
|
-
const prNumber =
|
|
71
|
+
const frontmatter = parseTypedTaskFrontmatter(fs.readFileSync(resolved.taskMdPath, 'utf8'));
|
|
72
|
+
const fact = readPrDeliveryFact(frontmatter);
|
|
73
|
+
const prNumber = fact.status === 'valid' && fact.fact.state === 'bound' ? fact.fact.identity.number : null;
|
|
73
74
|
return { ...platformResult('no-op'), task: { id: resolved.taskId, prNumber }, artifacts: canonicalArtifacts(resolved.taskDir) };
|
|
74
75
|
}
|
|
75
76
|
|
|
@@ -105,9 +106,11 @@ function syncPullRequestSummary(taskRef: string, options: { agent: string; body:
|
|
|
105
106
|
};
|
|
106
107
|
const resolved = resolveTaskRef(taskRef, options.cwd ? { repoRoot: options.cwd } : {});
|
|
107
108
|
if (!resolved.ok) return softenFailure(platformResult('failed', { error: { code: resolved.code, message: resolved.message, retryable: false } }));
|
|
108
|
-
const frontmatter =
|
|
109
|
-
const
|
|
110
|
-
if (
|
|
109
|
+
const frontmatter = parseTypedTaskFrontmatter(fs.readFileSync(resolved.taskMdPath, 'utf8'));
|
|
110
|
+
const fact = readPrDeliveryFact(frontmatter);
|
|
111
|
+
if (fact.status === 'invalid') return softenFailure(platformResult('failed', { error: { code: 'PR_DELIVERY_FACT_INVALID', message: fact.error.message, retryable: false } }));
|
|
112
|
+
const prNumber = fact.status === 'valid' && fact.fact.state === 'bound' ? fact.fact.identity.number : null;
|
|
113
|
+
if (!prNumber) return softenFailure(platformResult('failed', { error: { code: fact.status === 'missing' ? 'PR_DELIVERY_FACT_MISSING' : 'PR_NOT_LINKED', message: 'Task has no verified bound pull request', retryable: false } }));
|
|
111
114
|
knownPrNumber = prNumber;
|
|
112
115
|
const client = options.client || createGitHubClient();
|
|
113
116
|
const context = resolvePlatformContext({ cwd: resolved.repoRoot, client });
|