@fitlab-ai/agent-infra 0.11.4 → 0.11.6
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/bin/internal-cli.js +0 -5
- package/dist/lib/decide.js +4 -41
- package/dist/lib/git/branch-worktree.js +45 -0
- package/dist/lib/internal/cli-route-inventory.js +0 -3
- package/dist/lib/internal/task-activity.js +7 -40
- package/dist/lib/internal/task-event.js +4 -37
- package/dist/lib/internal/task-finalization.js +9 -2
- package/dist/lib/internal/task-ledger.js +5 -43
- package/dist/lib/internal/task-lifecycle.js +1 -1
- package/dist/lib/internal/task-operation-registry.js +1 -4
- package/dist/lib/internal/task-review.js +5 -37
- package/dist/lib/internal/task-verify.js +3 -47
- package/dist/lib/internal/task-warning.js +4 -40
- package/dist/lib/merge.js +62 -10
- package/dist/lib/platform/github-provider.js +9 -14
- package/dist/lib/platform/github-release-notes.js +80 -11
- package/dist/lib/platform/none-provider.js +1 -1
- package/dist/lib/platform/pr-summary.js +4 -23
- package/dist/lib/platform/provider-contract.d.ts +39 -16
- package/dist/lib/platform/provider-contract.js +1 -1
- package/dist/lib/platform/provider-validation.js +83 -13
- package/dist/lib/platform/release-notes.js +7 -8
- package/dist/lib/platform/verification-sync.js +12 -49
- package/dist/lib/sandbox/capture.js +1 -1
- package/dist/lib/sandbox/commands/create.js +46 -1
- package/dist/lib/sandbox/commands/enter.js +1 -1
- package/dist/lib/sandbox/commands/start.js +1 -1
- package/dist/lib/sandbox/config.js +10 -0
- package/dist/lib/sandbox/control/client.js +4 -1
- package/dist/lib/sandbox/control/executor.js +12 -4
- package/dist/lib/sandbox/control/lifecycle.js +18 -13
- package/dist/lib/sandbox/control/protocol.js +2 -1
- package/dist/lib/sandbox/removal.js +15 -8
- package/dist/lib/sandbox/task-resolver.js +62 -2
- package/dist/lib/task/activity-intent.js +1 -2
- package/dist/lib/task/artifact-operations.js +36 -2
- package/dist/lib/task/artifact-schema.js +7 -7
- package/dist/lib/task/control-authority.js +9 -166
- package/dist/lib/task/decision-intents.js +2 -4
- package/dist/lib/task/events.js +7 -28
- package/dist/lib/task/finalization-handoff.js +92 -0
- package/dist/lib/task/finalization.js +123 -12
- package/dist/lib/task/intermediate-cleanup.js +9 -148
- package/dist/lib/task/ledger-intents.js +3 -6
- package/dist/lib/task/lifecycle.js +50 -11
- package/dist/lib/task/local-artifact-finalization.js +13 -28
- package/dist/lib/task/resolve-ref.js +3 -3
- package/dist/lib/task/review-command.js +1 -2
- package/dist/lib/task/review-finalization.js +1 -2
- package/dist/lib/task/snapshot.js +6 -6
- package/dist/lib/task/verification-engine.js +16 -11
- package/dist/lib/task/verification.js +1 -13
- package/dist/lib/task/workflow-warning-intents.js +2 -4
- package/dist/lib/task/write.js +122 -3
- package/dist/lifecycle-build-manifest.json +3 -3
- package/lib/decide.ts +5 -35
- package/lib/git/branch-worktree.ts +41 -0
- package/lib/internal/cli-route-inventory.ts +0 -2
- package/lib/internal/task-activity.ts +6 -34
- package/lib/internal/task-event.ts +4 -37
- package/lib/internal/task-finalization.ts +9 -2
- package/lib/internal/task-ledger.ts +5 -38
- package/lib/internal/task-lifecycle.ts +2 -2
- package/lib/internal/task-operation-registry.ts +1 -4
- package/lib/internal/task-review.ts +5 -31
- package/lib/internal/task-verify.ts +3 -39
- package/lib/internal/task-warning.ts +3 -32
- package/lib/merge.ts +59 -10
- package/lib/platform/github-provider.ts +11 -18
- package/lib/platform/github-release-notes.ts +89 -14
- package/lib/platform/none-provider.ts +1 -1
- package/lib/platform/pr-summary.ts +4 -25
- package/lib/platform/provider-contract.ts +38 -12
- package/lib/platform/provider-validation.ts +83 -12
- package/lib/platform/release-notes.ts +11 -12
- package/lib/platform/verification-sync.ts +13 -53
- package/lib/sandbox/capture.ts +1 -1
- package/lib/sandbox/commands/create.ts +52 -1
- package/lib/sandbox/commands/enter.ts +1 -1
- package/lib/sandbox/commands/start.ts +1 -1
- package/lib/sandbox/config.ts +12 -0
- package/lib/sandbox/control/client.ts +5 -1
- package/lib/sandbox/control/executor.ts +13 -4
- package/lib/sandbox/control/lifecycle.ts +22 -13
- package/lib/sandbox/control/protocol.ts +3 -2
- package/lib/sandbox/removal.ts +23 -7
- package/lib/sandbox/task-resolver.ts +51 -2
- package/lib/task/activity-intent.ts +1 -2
- package/lib/task/artifact-operations.ts +58 -2
- package/lib/task/artifact-schema.ts +9 -7
- package/lib/task/control-authority.ts +14 -188
- package/lib/task/decision-intents.ts +2 -4
- package/lib/task/events.ts +8 -27
- package/lib/task/finalization-handoff.ts +104 -0
- package/lib/task/finalization.ts +120 -12
- package/lib/task/intermediate-cleanup.ts +9 -125
- package/lib/task/ledger-intents.ts +3 -6
- package/lib/task/lifecycle.ts +45 -13
- package/lib/task/local-artifact-finalization.ts +16 -35
- package/lib/task/resolve-ref.ts +3 -3
- package/lib/task/review-command.ts +2 -5
- package/lib/task/review-finalization.ts +1 -4
- package/lib/task/snapshot.ts +6 -6
- package/lib/task/verification-engine.ts +20 -10
- package/lib/task/verification.ts +1 -15
- package/lib/task/workflow-warning-intents.ts +2 -4
- package/lib/task/write.ts +116 -5
- package/package.json +1 -1
- package/templates/.agents/rules/evidence-reporting.en.md +1 -2
- package/templates/.agents/rules/evidence-reporting.zh-CN.md +1 -2
- package/templates/.agents/skills/analyze-task/SKILL.en.md +11 -2
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +11 -2
- package/templates/.agents/skills/archive-tasks/SKILL.en.md +2 -2
- package/templates/.agents/skills/archive-tasks/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/archive-tasks/scripts/archive-tasks.sh +109 -6
- package/templates/.agents/skills/code-task/reference/report-template.en.md +6 -6
- package/templates/.agents/skills/code-task/reference/report-template.zh-CN.md +6 -6
- package/templates/.agents/skills/complete-manual-validation/config/verify.en.json +2 -2
- package/templates/.agents/skills/complete-manual-validation/config/verify.zh-CN.json +2 -2
- package/templates/.agents/skills/complete-manual-validation/reference/report-template.en.md +1 -3
- package/templates/.agents/skills/complete-manual-validation/reference/report-template.zh-CN.md +1 -3
- package/templates/.agents/skills/complete-task/config/verify.en.json +2 -2
- package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +2 -2
- package/templates/.agents/skills/create-release-note/SKILL.en.md +17 -11
- package/templates/.agents/skills/create-release-note/SKILL.zh-CN.md +17 -11
- package/templates/.agents/skills/review-analysis/reference/report-template.en.md +3 -3
- package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +3 -3
- package/templates/.agents/skills/review-code/reference/report-template.en.md +3 -3
- package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +3 -3
- package/templates/.agents/skills/review-plan/reference/report-template.en.md +3 -3
- package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +3 -3
- package/templates/.agents/skills/review-pr/config/verify.en.json +3 -1
- package/templates/.agents/skills/review-pr/config/verify.zh-CN.json +3 -1
- package/templates/.agents/skills/review-pr/reference/report-template.en.md +3 -3
- package/templates/.agents/skills/review-pr/reference/report-template.zh-CN.md +3 -3
- package/templates/.agents/skills/run-manual-validation/config/verify.en.json +2 -2
- package/templates/.agents/skills/run-manual-validation/config/verify.zh-CN.json +2 -2
- package/templates/.agents/skills/run-manual-validation/reference/report-template.en.md +2 -2
- package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +2 -2
- package/dist/lib/internal/task-override.js +0 -138
- package/dist/lib/task/artifact-recovery.js +0 -476
- package/dist/lib/task/artifact-repair-intent.js +0 -181
- package/dist/lib/task/guard-override.js +0 -31
- package/dist/lib/task/human-override.js +0 -1259
- package/lib/internal/task-override.ts +0 -144
- package/lib/task/artifact-recovery.ts +0 -572
- package/lib/task/artifact-repair-intent.ts +0 -227
- package/lib/task/guard-override.ts +0 -50
- package/lib/task/human-override.ts +0 -1522
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { applyWorkflowWarningIntent } from '../task/workflow-warning-intents.js';
|
|
2
|
-
import { consumeHumanOverride, failureId, overrideDryRunConflict } from '../task/human-override.js';
|
|
3
2
|
import { resolveTaskRef } from '../task/resolve-ref.js';
|
|
4
3
|
import { TaskExecutionLockError, withTaskExecutionLock } from '../task/task-execution-lock.js';
|
|
5
4
|
import { ensureInternalHandlerRoute, internalHandlerRoute } from './cli-route-inventory.js';
|
|
6
5
|
const USAGE = `Usage: agent-infra-internal task-warning <task-ref> <add|set-status|list> [intent flags] [--dry-run]\n`;
|
|
7
6
|
const FLAGS = {
|
|
8
7
|
'--step': 'step', '--severity': 'severity', '--code': 'code', '--target': 'target',
|
|
9
|
-
'--message': 'message', '--action': 'action', '--id': 'id', '--status': 'status', '--resolution': 'resolution'
|
|
10
|
-
'--override-ticket': 'overrideTicket', '--override-target': 'overrideTarget', '--override-scope': 'overrideScope'
|
|
8
|
+
'--message': 'message', '--action': 'action', '--id': 'id', '--status': 'status', '--resolution': 'resolution'
|
|
11
9
|
};
|
|
12
10
|
function usageFailure(message) {
|
|
13
11
|
process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'WARNING_PAYLOAD_INVALID', message } })}\n`);
|
|
@@ -66,9 +64,6 @@ async function taskWarning(args = []) {
|
|
|
66
64
|
};
|
|
67
65
|
const optional = kind === 'list' ? ['status'] : [];
|
|
68
66
|
const allowed = new Set(['kind', 'taskRef', 'dryRun', ...required[kind], ...optional]);
|
|
69
|
-
allowed.add('overrideTicket');
|
|
70
|
-
allowed.add('overrideTarget');
|
|
71
|
-
allowed.add('overrideScope');
|
|
72
67
|
const unexpected = Object.keys(values).find((key) => !allowed.has(key));
|
|
73
68
|
const missing = required[kind].find((key) => values[key] === undefined);
|
|
74
69
|
if (unexpected) {
|
|
@@ -79,43 +74,14 @@ async function taskWarning(args = []) {
|
|
|
79
74
|
usageFailure(`${kind} requires '${missing}'`);
|
|
80
75
|
return;
|
|
81
76
|
}
|
|
82
|
-
const dryRunConflict = overrideDryRunConflict(values);
|
|
83
|
-
if (dryRunConflict) {
|
|
84
|
-
usageFailure(dryRunConflict.message);
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
77
|
const resolved = resolveTaskRef(taskRef);
|
|
88
78
|
if (!resolved.ok) {
|
|
89
79
|
usageFailure(resolved.message);
|
|
90
80
|
return;
|
|
91
81
|
}
|
|
92
82
|
let result;
|
|
93
|
-
let humanOverride = null;
|
|
94
83
|
try {
|
|
95
|
-
result = await withTaskExecutionLock(resolved.repoRoot, resolved.taskId, `task-warning.${kind}`, async () =>
|
|
96
|
-
let current = applyWorkflowWarningIntent(values);
|
|
97
|
-
if (current.status !== 'failed' || !values.overrideTicket)
|
|
98
|
-
return current;
|
|
99
|
-
if (!values.overrideTarget || !values.overrideScope) {
|
|
100
|
-
usageFailure('override ticket requires target and scope');
|
|
101
|
-
return current;
|
|
102
|
-
}
|
|
103
|
-
const consumed = await consumeHumanOverride({
|
|
104
|
-
taskRef, ticketId: String(values.overrideTicket),
|
|
105
|
-
failureId: failureId('workflow-warning', current.error?.code ?? 'TASK_STATE_MISMATCH'),
|
|
106
|
-
target: String(values.overrideTarget), scope: String(values.overrideScope)
|
|
107
|
-
}, {
|
|
108
|
-
effectExecutor: (capability) => {
|
|
109
|
-
const retried = applyWorkflowWarningIntent(values, { manualOverride: capability });
|
|
110
|
-
current = retried;
|
|
111
|
-
return retried.status === 'failed' || retried.status === 'planned'
|
|
112
|
-
? { code: 'OVERRIDE_EFFECT_FAILED', message: retried.status === 'planned' ? 'producer returned planned; no workflow warning effect was committed' : `${retried.error?.code ?? 'WARNING_FAILED'}: ${retried.error?.message ?? 'manual warning effect failed'}` }
|
|
113
|
-
: null;
|
|
114
|
-
}
|
|
115
|
-
});
|
|
116
|
-
humanOverride = consumed;
|
|
117
|
-
return current;
|
|
118
|
-
});
|
|
84
|
+
result = await withTaskExecutionLock(resolved.repoRoot, resolved.taskId, `task-warning.${kind}`, async () => applyWorkflowWarningIntent(values));
|
|
119
85
|
}
|
|
120
86
|
catch (error) {
|
|
121
87
|
if (!(error instanceof TaskExecutionLockError))
|
|
@@ -124,10 +90,8 @@ async function taskWarning(args = []) {
|
|
|
124
90
|
process.exitCode = 1;
|
|
125
91
|
return;
|
|
126
92
|
}
|
|
127
|
-
process.stdout.write(`${JSON.stringify(
|
|
128
|
-
|
|
129
|
-
humanOverride.status === 'failed');
|
|
130
|
-
if (result.status === 'failed' || overrideFailed)
|
|
93
|
+
process.stdout.write(`${JSON.stringify(result)}\n`);
|
|
94
|
+
if (result.status === 'failed')
|
|
131
95
|
process.exitCode = 1;
|
|
132
96
|
}
|
|
133
97
|
export { taskWarning };
|
package/dist/lib/merge.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
+
import crypto from 'node:crypto';
|
|
3
4
|
import { removeDirRecursive } from './remove-dir.js';
|
|
4
5
|
import { validateCurrentTaskContract } from './task/current-contract.js';
|
|
5
6
|
const TASK_ID_RE = /^TASK-\d{8}-\d{6}$/;
|
|
@@ -44,7 +45,7 @@ function extractTitle(content) {
|
|
|
44
45
|
.replace(/\|/g, '\\|') || null;
|
|
45
46
|
}
|
|
46
47
|
function normalizeTaskRecord(taskDir, taskFile, dateParts) {
|
|
47
|
-
const taskId = path.basename(taskDir);
|
|
48
|
+
const taskId = path.basename(taskDir) === 'local' ? path.basename(path.dirname(taskDir)) : path.basename(taskDir);
|
|
48
49
|
const content = fs.readFileSync(taskFile, 'utf8');
|
|
49
50
|
const completedAt = extractField(content, 'completed_at');
|
|
50
51
|
const updatedAt = extractField(content, 'updated_at');
|
|
@@ -85,7 +86,7 @@ function scanSourceTasks(sourceDir) {
|
|
|
85
86
|
if (!taskEntry.isDirectory() || !TASK_ID_RE.test(taskEntry.name)) {
|
|
86
87
|
continue;
|
|
87
88
|
}
|
|
88
|
-
const taskDir = path.join(dayDir, taskEntry.name);
|
|
89
|
+
const taskDir = path.join(dayDir, taskEntry.name, 'local');
|
|
89
90
|
const taskFile = path.join(taskDir, 'task.md');
|
|
90
91
|
if (!fs.existsSync(taskFile)) {
|
|
91
92
|
continue;
|
|
@@ -165,7 +166,7 @@ function collectArchiveEntries(archiveDir) {
|
|
|
165
166
|
continue;
|
|
166
167
|
}
|
|
167
168
|
const taskDir = path.join(dayDir, taskEntry.name);
|
|
168
|
-
const taskFile = path.join(taskDir, 'task.md');
|
|
169
|
+
const taskFile = path.join(taskDir, 'local', 'task.md');
|
|
169
170
|
const relativePath = `${yearEntry.name}/${monthEntry.name}/${dayEntry.name}/${taskEntry.name}/`;
|
|
170
171
|
let title = taskEntry.name;
|
|
171
172
|
let type = 'unknown';
|
|
@@ -471,9 +472,10 @@ function validateSourceRoot(sourceRoot) {
|
|
|
471
472
|
invalidSource('source path must be a real directory');
|
|
472
473
|
}
|
|
473
474
|
}
|
|
474
|
-
function validateTaskDirectory(sourceRoot, taskDir, seenTaskIds) {
|
|
475
|
+
function validateTaskDirectory(sourceRoot, taskDir, seenTaskIds, archived = false) {
|
|
475
476
|
const taskId = path.basename(taskDir);
|
|
476
|
-
const
|
|
477
|
+
const contentDir = archived ? path.join(taskDir, 'local') : taskDir;
|
|
478
|
+
const taskFile = path.join(contentDir, 'task.md');
|
|
477
479
|
const taskDirStat = sourcePathStat(sourceRoot, taskDir);
|
|
478
480
|
if (!taskDirStat || !taskDirStat.isDirectory()) {
|
|
479
481
|
invalidSource(`${sourceRelativePath(sourceRoot, taskDir)} must be a directory`);
|
|
@@ -491,12 +493,63 @@ function validateTaskDirectory(sourceRoot, taskDir, seenTaskIds) {
|
|
|
491
493
|
invalidSource(`${sourceRelativePath(sourceRoot, taskFile)} id '${String(contract.metadata.id ?? 'missing')}' does not match directory '${taskId}'`);
|
|
492
494
|
}
|
|
493
495
|
validateTaskTree(sourceRoot, taskDir);
|
|
496
|
+
if (archived) {
|
|
497
|
+
for (const entry of fs.readdirSync(taskDir, { withFileTypes: true })) {
|
|
498
|
+
if (!['local', 'github', 'derived'].includes(entry.name) || !entry.isDirectory()) {
|
|
499
|
+
invalidSource(`${sourceRelativePath(sourceRoot, path.join(taskDir, entry.name))} is not an allowed archive source directory`);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
validateArchiveSource(sourceRoot, contentDir);
|
|
503
|
+
const githubDir = path.join(taskDir, 'github');
|
|
504
|
+
if (fs.existsSync(githubDir)) {
|
|
505
|
+
for (const capture of fs.readdirSync(githubDir, { withFileTypes: true })) {
|
|
506
|
+
const captureDir = path.join(githubDir, capture.name);
|
|
507
|
+
if (!capture.isDirectory() || !/^capture-[A-Za-z0-9._-]+$/.test(capture.name) || !fs.existsSync(path.join(captureDir, 'capture.md'))) {
|
|
508
|
+
invalidSource(`${sourceRelativePath(sourceRoot, captureDir)} is not a valid GitHub capture`);
|
|
509
|
+
}
|
|
510
|
+
validateArchiveSource(sourceRoot, captureDir);
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
const derivedDir = path.join(taskDir, 'derived');
|
|
514
|
+
if (fs.existsSync(derivedDir)) {
|
|
515
|
+
for (const view of fs.readdirSync(derivedDir, { withFileTypes: true })) {
|
|
516
|
+
const viewDir = path.join(derivedDir, view.name);
|
|
517
|
+
if (!view.isDirectory() || !fs.existsSync(path.join(viewDir, 'inputs.md'))) {
|
|
518
|
+
invalidSource(`${sourceRelativePath(sourceRoot, viewDir)} requires inputs.md`);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
}
|
|
494
523
|
const previousPath = seenTaskIds.get(taskId);
|
|
495
524
|
if (previousPath) {
|
|
496
525
|
invalidSource(`duplicate task ID ${taskId} at ${previousPath} and ${sourceRelativePath(sourceRoot, taskDir)}`);
|
|
497
526
|
}
|
|
498
527
|
seenTaskIds.set(taskId, sourceRelativePath(sourceRoot, taskDir));
|
|
499
528
|
}
|
|
529
|
+
function validateArchiveSource(sourceRoot, sourceDir) {
|
|
530
|
+
const hashFile = path.join(sourceDir, 'contents.sha256');
|
|
531
|
+
const hashStat = sourcePathStat(sourceRoot, hashFile);
|
|
532
|
+
if (!hashStat?.isFile())
|
|
533
|
+
invalidSource(`${sourceRelativePath(sourceRoot, sourceDir)} requires contents.sha256`);
|
|
534
|
+
const files = [];
|
|
535
|
+
const walk = (dir) => {
|
|
536
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
537
|
+
const target = path.join(dir, entry.name);
|
|
538
|
+
if (entry.name === 'manifest.md')
|
|
539
|
+
invalidSource(`${sourceRelativePath(sourceRoot, target)} is forbidden inside a TASK`);
|
|
540
|
+
if (entry.isDirectory())
|
|
541
|
+
walk(target);
|
|
542
|
+
else if (entry.isFile() && target !== hashFile)
|
|
543
|
+
files.push(target);
|
|
544
|
+
}
|
|
545
|
+
};
|
|
546
|
+
walk(sourceDir);
|
|
547
|
+
const expected = files.sort((a, b) => Buffer.compare(Buffer.from(path.relative(sourceDir, a).split(path.sep).join('/')), Buffer.from(path.relative(sourceDir, b).split(path.sep).join('/'))))
|
|
548
|
+
.map((file) => `${crypto.createHash('sha256').update(fs.readFileSync(file)).digest('hex')} ${path.relative(sourceDir, file).split(path.sep).join('/')}`);
|
|
549
|
+
const actual = fs.readFileSync(hashFile, 'utf8').trimEnd().split(/\r?\n/).filter(Boolean);
|
|
550
|
+
if (JSON.stringify(expected) !== JSON.stringify(actual))
|
|
551
|
+
invalidSource(`${sourceRelativePath(sourceRoot, hashFile)} does not match local files`);
|
|
552
|
+
}
|
|
500
553
|
function validateMutableSection(sourceRoot, section, seenTaskIds) {
|
|
501
554
|
const sectionDir = path.join(sourceRoot, section);
|
|
502
555
|
const sectionStat = sourcePathStat(sourceRoot, sectionDir);
|
|
@@ -561,9 +614,6 @@ function validateArchiveSection(sourceRoot, seenTaskIds) {
|
|
|
561
614
|
const monthDir = monthPath;
|
|
562
615
|
for (const dayEntry of fs.readdirSync(monthDir, { withFileTypes: true })) {
|
|
563
616
|
const dayPath = path.join(monthDir, dayEntry.name);
|
|
564
|
-
if (allowManifest(monthDir, dayEntry)) {
|
|
565
|
-
continue;
|
|
566
|
-
}
|
|
567
617
|
const dayStat = sourcePathStat(sourceRoot, dayPath);
|
|
568
618
|
if (!dayStat?.isDirectory() || !/^\d{2}$/.test(dayEntry.name)) {
|
|
569
619
|
invalidSource(`${sourceRelativePath(sourceRoot, dayPath)} is not a DD directory or manifest.md`);
|
|
@@ -575,7 +625,7 @@ function validateArchiveSection(sourceRoot, seenTaskIds) {
|
|
|
575
625
|
if (!taskStat?.isDirectory() || !TASK_ID_RE.test(taskEntry.name)) {
|
|
576
626
|
invalidSource(`${sourceRelativePath(sourceRoot, taskPath)} is not a TASK-YYYYMMDD-HHMMSS directory`);
|
|
577
627
|
}
|
|
578
|
-
validateTaskDirectory(sourceRoot, taskPath, seenTaskIds);
|
|
628
|
+
validateTaskDirectory(sourceRoot, taskPath, seenTaskIds, true);
|
|
579
629
|
}
|
|
580
630
|
}
|
|
581
631
|
}
|
|
@@ -716,9 +766,10 @@ function mergeArchiveSection(sourceArchive, localArchive, report) {
|
|
|
716
766
|
});
|
|
717
767
|
continue;
|
|
718
768
|
}
|
|
769
|
+
const sourceTaskDir = path.dirname(task.taskDir);
|
|
719
770
|
const destinationDir = path.join(localArchive, task.relativePath);
|
|
720
771
|
fs.mkdirSync(path.dirname(destinationDir), { recursive: true });
|
|
721
|
-
fs.cpSync(
|
|
772
|
+
fs.cpSync(sourceTaskDir, destinationDir, { recursive: true });
|
|
722
773
|
recordArchive(report, 'copied', {
|
|
723
774
|
action: 'copied',
|
|
724
775
|
symbol: '✓',
|
|
@@ -829,6 +880,7 @@ async function cmdMerge(args) {
|
|
|
829
880
|
const report = createReport(resolvedSource, backupRootRelative);
|
|
830
881
|
detectSourceMode(resolvedSource);
|
|
831
882
|
validateSourceWorkspace(resolvedSource);
|
|
883
|
+
validateArchiveSection(workspaceDir, new Map());
|
|
832
884
|
for (const section of ALL_SECTIONS) {
|
|
833
885
|
fs.mkdirSync(path.join(workspaceDir, section), { recursive: true });
|
|
834
886
|
}
|
|
@@ -921,26 +921,21 @@ function createGitHubOperations(client) {
|
|
|
921
921
|
}
|
|
922
922
|
const mergedPullRequests = collected.pullRequests.map((item) => ({
|
|
923
923
|
id: String(item.number), identity: { kind: 'number', value: Number(item.number) }, number: Number(item.number),
|
|
924
|
-
|
|
924
|
+
title: String(item.title || ''), body: String(item.body || ''),
|
|
925
925
|
mergedAt: new Date(String(item.mergedAt)).toISOString(), displayUrl: String(item.url || ''),
|
|
926
926
|
labels: Array.isArray(item.labels) ? item.labels.map((label) => String(label.name || label)) : [],
|
|
927
|
-
|
|
927
|
+
author: item.author,
|
|
928
|
+
closingIssues: item.closingIssues.map((issue) => ({
|
|
929
|
+
id: String(issue.number), identity: { kind: 'number', value: Number(issue.number) }, number: Number(issue.number),
|
|
930
|
+
title: String(issue.title || ''), displayUrl: String(issue.url || ''), author: issue.author
|
|
931
|
+
}))
|
|
928
932
|
}));
|
|
929
|
-
const closingIssues = collected.pullRequests.flatMap((item) => Array.isArray(item.closingIssuesReferences) ? item.closingIssuesReferences.map((issue) => ({
|
|
930
|
-
id: String(issue.number), identity: { kind: 'number', value: Number(issue.number) }, number: Number(issue.number),
|
|
931
|
-
state: 'closed', title: String(issue.title || ''), body: '', labels: Array.isArray(issue.labels) ? issue.labels.map((label) => String(label.name || label)) : [],
|
|
932
|
-
assignees: [], milestone: null, fields: {}, displayUrl: String(issue.url || '')
|
|
933
|
-
})) : []);
|
|
934
|
-
const actors = [...collected.authors.values()].flatMap((items) => items.map((item) => ({
|
|
935
|
-
...(item.login ? { id: String(item.login) } : {}), ...(item.name ? { name: String(item.name) } : {})
|
|
936
|
-
})));
|
|
937
933
|
return {
|
|
938
934
|
ok: true,
|
|
939
935
|
value: {
|
|
940
|
-
history:
|
|
936
|
+
history: collected.history,
|
|
937
|
+
commits: collected.commits,
|
|
941
938
|
mergedPullRequests,
|
|
942
|
-
closingIssues,
|
|
943
|
-
actors
|
|
944
939
|
}
|
|
945
940
|
};
|
|
946
941
|
}
|
|
@@ -1121,7 +1116,7 @@ function createGitHubOperations(client) {
|
|
|
1121
1116
|
function createGitHubProvider(input, client = createGitHubClient()) {
|
|
1122
1117
|
return {
|
|
1123
1118
|
type: input.providerType,
|
|
1124
|
-
contractVersion:
|
|
1119
|
+
contractVersion: 2,
|
|
1125
1120
|
identity: { issue: 'number', 'pull-request': 'number', comment: 'number', release: 'key' },
|
|
1126
1121
|
...createGitHubOperations(client),
|
|
1127
1122
|
context: {
|
|
@@ -9,12 +9,22 @@ function normalizeGitHubActor(actor) {
|
|
|
9
9
|
const login = platformLogin || noReplyLogin;
|
|
10
10
|
return {
|
|
11
11
|
name,
|
|
12
|
-
email,
|
|
13
12
|
login,
|
|
14
13
|
bot: Boolean(login?.endsWith('[bot]')),
|
|
15
14
|
resolution: platformLogin ? 'platform-user' : noReplyLogin ? 'platform-noreply' : 'unresolved'
|
|
16
15
|
};
|
|
17
16
|
}
|
|
17
|
+
function normalizePlatformAuthor(author) {
|
|
18
|
+
if (!author)
|
|
19
|
+
return null;
|
|
20
|
+
const login = author.login?.trim().toLowerCase() || null;
|
|
21
|
+
return {
|
|
22
|
+
name: login || '',
|
|
23
|
+
login,
|
|
24
|
+
bot: Boolean(login?.endsWith('[bot]')),
|
|
25
|
+
resolution: login ? 'platform-user' : 'unresolved'
|
|
26
|
+
};
|
|
27
|
+
}
|
|
18
28
|
function failure(error) {
|
|
19
29
|
return {
|
|
20
30
|
status: error.retryable ? 'blocked' : 'failed',
|
|
@@ -66,31 +76,90 @@ function fetchGitHubReleaseNoteData(input, options = {}) {
|
|
|
66
76
|
return failure(viewed.error);
|
|
67
77
|
history.push({ tag: String(item.tagName), body: String(viewed.value.body || ''), url: viewed.value.url || null });
|
|
68
78
|
}
|
|
69
|
-
const prs = client.json(['pr', 'list', '--repo', input.repository, '--state', 'merged', '--base', input.branch, '--limit', '1000', '--json', 'number,title,body,url,mergedAt,labels,author
|
|
79
|
+
const prs = client.json(['pr', 'list', '--repo', input.repository, '--state', 'merged', '--base', input.branch, '--limit', '1000', '--json', 'number,title,body,url,mergedAt,labels,author'], { cwd: options.cwd });
|
|
70
80
|
if (!prs.ok)
|
|
71
81
|
return failure(prs.error);
|
|
72
82
|
const authors = new Map();
|
|
83
|
+
const fromTime = Date.parse(input.fromTime);
|
|
84
|
+
const toTime = Date.parse(input.toTime);
|
|
85
|
+
const pullRequests = prs.value.filter((item) => {
|
|
86
|
+
const mergedAt = Date.parse(String(item.mergedAt || ''));
|
|
87
|
+
return Number.isFinite(mergedAt) && mergedAt > fromTime && mergedAt <= toTime;
|
|
88
|
+
});
|
|
89
|
+
const eligiblePullRequestNumbers = new Set(pullRequests.map((item) => Number(item.number)));
|
|
90
|
+
const pullRequestNumbersByCommit = new Map();
|
|
73
91
|
for (const oid of input.commitOids) {
|
|
74
|
-
const query = `query($owner:String!,$name:String!,$oid:GitObjectID!){repository(owner:$owner,name:$name){object(oid:$oid){... on Commit{authors(first:100){nodes{name email user{login}} pageInfo{hasNextPage}}}}}}`;
|
|
92
|
+
const query = `query($owner:String!,$name:String!,$oid:GitObjectID!){repository(owner:$owner,name:$name){object(oid:$oid){... on Commit{authors(first:100){nodes{name email user{login}} pageInfo{hasNextPage}} associatedPullRequests(first:100){nodes{number} pageInfo{hasNextPage}}}}}}`;
|
|
75
93
|
const [owner, name] = input.repository.split('/');
|
|
76
94
|
const result = client.json([
|
|
77
95
|
'api', 'graphql', '-f', `query=${query}`, '-F', `owner=${owner}`, '-F', `name=${name}`, '-F', `oid=${oid}`
|
|
78
96
|
], { cwd: options.cwd });
|
|
79
97
|
if (!result.ok)
|
|
80
98
|
return failure(result.error);
|
|
81
|
-
const
|
|
99
|
+
const object = result.value.data?.repository?.object;
|
|
100
|
+
const connection = object?.authors;
|
|
82
101
|
if (connection?.pageInfo?.hasNextPage) {
|
|
83
102
|
return failure({ code: 'RELEASE_NOTES_AUTHORS_TRUNCATED', message: `Commit authors exceeded the supported page size for ${oid}`, retryable: false });
|
|
84
103
|
}
|
|
85
104
|
authors.set(oid, (connection?.nodes || []).map(normalizeGitHubActor));
|
|
105
|
+
const associatedPullRequests = object?.associatedPullRequests;
|
|
106
|
+
if (!associatedPullRequests || !Array.isArray(associatedPullRequests.nodes) || !associatedPullRequests.pageInfo || typeof associatedPullRequests.pageInfo.hasNextPage !== 'boolean') {
|
|
107
|
+
return failure({ code: 'INVALID_PLATFORM_RESPONSE', message: `Associated pull request data is incomplete for commit ${oid}`, retryable: false });
|
|
108
|
+
}
|
|
109
|
+
if (associatedPullRequests.pageInfo.hasNextPage) {
|
|
110
|
+
return failure({ code: 'RELEASE_NOTES_ASSOCIATED_PULL_REQUESTS_TRUNCATED', message: `Associated pull requests exceeded the supported page size for ${oid}`, retryable: false });
|
|
111
|
+
}
|
|
112
|
+
const numbers = [];
|
|
113
|
+
for (const association of associatedPullRequests.nodes) {
|
|
114
|
+
if (typeof association?.number !== 'number' || !Number.isSafeInteger(association.number)) {
|
|
115
|
+
return failure({ code: 'INVALID_PLATFORM_RESPONSE', message: `Associated pull request identity is incomplete for commit ${oid}`, retryable: false });
|
|
116
|
+
}
|
|
117
|
+
if (eligiblePullRequestNumbers.has(association.number))
|
|
118
|
+
numbers.push(association.number);
|
|
119
|
+
}
|
|
120
|
+
pullRequestNumbersByCommit.set(oid, [...new Set(numbers)]);
|
|
86
121
|
}
|
|
87
|
-
const
|
|
88
|
-
const
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
122
|
+
const resolvedPullRequests = [];
|
|
123
|
+
const [owner, name] = input.repository.split('/');
|
|
124
|
+
const closingIssuesQuery = 'query($owner:String!,$name:String!,$number:Int!,$cursor:String){repository(owner:$owner,name:$name){pullRequest(number:$number){closingIssuesReferences(first:100,after:$cursor){nodes{number title url author{login}} pageInfo{hasNextPage endCursor}}}}}';
|
|
125
|
+
for (const item of pullRequests) {
|
|
126
|
+
const closingIssues = [];
|
|
127
|
+
let cursor = null;
|
|
128
|
+
for (;;) {
|
|
129
|
+
const args = ['api', 'graphql', '-f', `query=${closingIssuesQuery}`, '-F', `owner=${owner}`, '-F', `name=${name}`, '-F', `number=${String(item.number)}`];
|
|
130
|
+
if (cursor)
|
|
131
|
+
args.push('-F', `cursor=${cursor}`);
|
|
132
|
+
const response = client.json(args, { cwd: options.cwd });
|
|
133
|
+
if (!response.ok)
|
|
134
|
+
return failure(response.error);
|
|
135
|
+
const connection = response.value.data?.repository?.pullRequest?.closingIssuesReferences;
|
|
136
|
+
if (!connection || !Array.isArray(connection.nodes) || !connection.pageInfo || typeof connection.pageInfo.hasNextPage !== 'boolean') {
|
|
137
|
+
return failure({ code: 'INVALID_PLATFORM_RESPONSE', message: `Closing Issue data is incomplete for pull request ${String(item.number)}`, retryable: false });
|
|
138
|
+
}
|
|
139
|
+
closingIssues.push(...connection.nodes.map((issue) => ({
|
|
140
|
+
number: Number(issue.number), title: String(issue.title || ''), url: String(issue.url || ''),
|
|
141
|
+
author: normalizePlatformAuthor(issue.author)
|
|
142
|
+
})));
|
|
143
|
+
if (!connection.pageInfo.hasNextPage)
|
|
144
|
+
break;
|
|
145
|
+
if (!connection.pageInfo.endCursor || connection.pageInfo.endCursor === cursor) {
|
|
146
|
+
return failure({ code: 'PAGINATION_INVALID', message: `Closing Issue pagination is incomplete for pull request ${String(item.number)}`, retryable: false });
|
|
147
|
+
}
|
|
148
|
+
cursor = connection.pageInfo.endCursor;
|
|
149
|
+
}
|
|
150
|
+
resolvedPullRequests.push({
|
|
151
|
+
...item,
|
|
152
|
+
author: normalizePlatformAuthor(item.author || null),
|
|
153
|
+
closingIssues
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
const commits = input.commitOids.map((sha) => ({
|
|
157
|
+
sha,
|
|
158
|
+
url: `https://github.com/${input.repository}/commit/${sha}`,
|
|
159
|
+
pullRequestNumbers: pullRequestNumbersByCommit.get(sha) || [],
|
|
160
|
+
authors: authors.get(sha) || []
|
|
161
|
+
}));
|
|
162
|
+
return { status: 'no-op', changed: false, history, pullRequests: resolvedPullRequests, commits, error: null };
|
|
94
163
|
}
|
|
95
164
|
export { fetchGitHubReleaseNoteData, normalizeGitHubActor, publishGitHubReleaseNotes };
|
|
96
165
|
//# sourceMappingURL=github-release-notes.js.map
|
|
@@ -2,13 +2,12 @@ import fs from 'node:fs';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { enumerateArtifacts } from '../task/artifacts.js';
|
|
4
4
|
import { parseTypedTaskFrontmatter } from '../task/frontmatter.js';
|
|
5
|
-
import { renderHumanOverrideAudit } from '../task/human-override.js';
|
|
6
5
|
import { resolveTaskRef } from '../task/resolve-ref.js';
|
|
7
6
|
import { TaskExecutionLockError, withTaskExecutionLock } from '../task/task-execution-lock.js';
|
|
8
7
|
import { readPrDeliveryFact } from '../task/pr-delivery-fact.js';
|
|
9
8
|
import { resolvePlatformProviderContext } from './context.js';
|
|
10
9
|
import { normalizeCommentContent } from './issue-comments.js';
|
|
11
|
-
import { CONTROL_MARKER_PATTERN,
|
|
10
|
+
import { CONTROL_MARKER_PATTERN, sanitizeMarkdownDocument, splitDocumentPlaceholder } from './comment-safety.js';
|
|
12
11
|
import { platformResult } from './types.js';
|
|
13
12
|
import { providerError, providerOperationContext, providerStatus, providerResourceToken, resourceIdentityNumber, unsupportedProviderOperation } from './provider-bridge.js';
|
|
14
13
|
import { resourceIdentityEquals } from './resource-identity.js';
|
|
@@ -18,23 +17,6 @@ import { readManualValidationCompletion } from '../task/manual-validation-comple
|
|
|
18
17
|
function summaryMarker(taskId) {
|
|
19
18
|
return `<!-- sync-pr:${taskId}:summary -->`;
|
|
20
19
|
}
|
|
21
|
-
function escapeSummaryAuditText(value) {
|
|
22
|
-
return escapeHtmlText(value).replace(/\r\n?/g, '\n');
|
|
23
|
-
}
|
|
24
|
-
function renderSummaryAuditLine(value) {
|
|
25
|
-
const safe = escapeSummaryAuditText(value);
|
|
26
|
-
const longestRun = Math.max(0, ...(safe.match(/`+/g) || []).map((run) => run.length));
|
|
27
|
-
const delimiter = '`'.repeat(longestRun + 1);
|
|
28
|
-
return `${delimiter} ${safe} ${delimiter}`;
|
|
29
|
-
}
|
|
30
|
-
function renderSafeHumanOverrideAudit(value) {
|
|
31
|
-
const normalized = value.trim().replace(/\r\n?/g, '\n');
|
|
32
|
-
if (!normalized)
|
|
33
|
-
return '';
|
|
34
|
-
const [heading, ...rows] = normalized.split('\n');
|
|
35
|
-
const safeHeading = heading === '## Human Override Audit' ? heading : renderSummaryAuditLine(heading || '');
|
|
36
|
-
return [safeHeading, ...rows.map((row) => row ? renderSummaryAuditLine(row) : '')].join('\n');
|
|
37
|
-
}
|
|
38
20
|
function isSafeSummaryEnvelope(value, taskId) {
|
|
39
21
|
return value.includes(summaryMarker(taskId))
|
|
40
22
|
&& (value.match(/<!--\s*sync-pr:/gi) || []).length === 1
|
|
@@ -71,9 +53,8 @@ function warningResultForPrimary(primaryResult) {
|
|
|
71
53
|
function platformError(error) {
|
|
72
54
|
return { code: error.code, message: error.message, retryable: error.retryable ?? false };
|
|
73
55
|
}
|
|
74
|
-
function buildPullRequestSummary(taskId, body, headSha
|
|
75
|
-
|
|
76
|
-
return normalizeCommentContent(`${summaryMarker(taskId)}\n<!-- last-commit: ${headSha} -->\n\n${sections}\n`);
|
|
56
|
+
function buildPullRequestSummary(taskId, body, headSha) {
|
|
57
|
+
return normalizeCommentContent(`${summaryMarker(taskId)}\n<!-- last-commit: ${headSha} -->\n\n${body.replace(/\s+$/, '')}\n`);
|
|
77
58
|
}
|
|
78
59
|
function reconcileSummaryComment(comments, taskId, desired) {
|
|
79
60
|
const marker = summaryMarker(taskId);
|
|
@@ -586,7 +567,7 @@ async function syncPullRequestSummary(taskRef, options) {
|
|
|
586
567
|
const renderedBody = manual?.phase === 'final'
|
|
587
568
|
? replaced.value.replace(MANUAL_VALIDATION_RECEIPT_PLACEHOLDER, `<!-- manual-validation-receipt: transaction=${manual.transactionId}; receipt=${manual.receiptDigest}; evidence=${manualEvidenceDigest}; head=${manual.prHeadSha} -->`)
|
|
588
569
|
: replaced.value;
|
|
589
|
-
const desired = buildPullRequestSummary(resolved.taskId, renderedBody, initial.value.head.sha
|
|
570
|
+
const desired = buildPullRequestSummary(resolved.taskId, renderedBody, initial.value.head.sha);
|
|
590
571
|
if (!isSafeSummaryEnvelope(desired, resolved.taskId))
|
|
591
572
|
return fail('failed', context, {
|
|
592
573
|
code: 'PR_SUMMARY_RENDER_INVALID',
|
|
@@ -242,22 +242,45 @@ type RepositoryMetadataSnapshot = {
|
|
|
242
242
|
}>;
|
|
243
243
|
}>;
|
|
244
244
|
};
|
|
245
|
+
type ReleaseNoteAuthor = {
|
|
246
|
+
name: string;
|
|
247
|
+
login: string | null;
|
|
248
|
+
bot: boolean;
|
|
249
|
+
resolution: 'platform-user' | 'platform-noreply' | 'unresolved';
|
|
250
|
+
};
|
|
251
|
+
type ReleaseNoteIssue = {
|
|
252
|
+
id: string;
|
|
253
|
+
identity: ResourceIdentity;
|
|
254
|
+
number: number;
|
|
255
|
+
title: string;
|
|
256
|
+
displayUrl: string;
|
|
257
|
+
author: ReleaseNoteAuthor | null;
|
|
258
|
+
};
|
|
259
|
+
type ReleaseNotePullRequest = {
|
|
260
|
+
id: string;
|
|
261
|
+
identity: ResourceIdentity;
|
|
262
|
+
number: number;
|
|
263
|
+
title: string;
|
|
264
|
+
body: string;
|
|
265
|
+
mergedAt: string;
|
|
266
|
+
displayUrl: string;
|
|
267
|
+
labels: string[];
|
|
268
|
+
author: ReleaseNoteAuthor | null;
|
|
269
|
+
closingIssues: ReleaseNoteIssue[];
|
|
270
|
+
};
|
|
245
271
|
type ReleaseNotesFacts = {
|
|
246
272
|
history: Array<{
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
author: {
|
|
251
|
-
id?: string;
|
|
252
|
-
name?: string;
|
|
253
|
-
} | null;
|
|
273
|
+
tag: string;
|
|
274
|
+
body: string;
|
|
275
|
+
url: string | null;
|
|
254
276
|
}>;
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
277
|
+
commits: Array<{
|
|
278
|
+
sha: string;
|
|
279
|
+
url: string | null;
|
|
280
|
+
pullRequestNumbers: number[];
|
|
281
|
+
authors: ReleaseNoteAuthor[];
|
|
260
282
|
}>;
|
|
283
|
+
mergedPullRequests: ReleaseNotePullRequest[];
|
|
261
284
|
};
|
|
262
285
|
type MilestoneReconciliation = {
|
|
263
286
|
changed: boolean;
|
|
@@ -276,13 +299,13 @@ type VerificationRemoteFacts = {
|
|
|
276
299
|
};
|
|
277
300
|
type PlatformProviderFactoryInput = {
|
|
278
301
|
providerType: string;
|
|
279
|
-
contractVersion:
|
|
302
|
+
contractVersion: 2;
|
|
280
303
|
repositoryRoot: string;
|
|
281
304
|
config: Readonly<Record<string, JsonValue>>;
|
|
282
305
|
};
|
|
283
306
|
type PlatformProvider = {
|
|
284
307
|
type: string;
|
|
285
|
-
contractVersion:
|
|
308
|
+
contractVersion: 2;
|
|
286
309
|
identity?: ProviderIdentityDeclaration;
|
|
287
310
|
context: {
|
|
288
311
|
resolve(input: {
|
|
@@ -548,8 +571,8 @@ type PlatformProvider = {
|
|
|
548
571
|
};
|
|
549
572
|
};
|
|
550
573
|
type PlatformProviderFactory = (input: PlatformProviderFactoryInput) => Promise<PlatformProvider>;
|
|
551
|
-
declare const PLATFORM_PROVIDER_CONTRACT_VERSION:
|
|
574
|
+
declare const PLATFORM_PROVIDER_CONTRACT_VERSION: 2;
|
|
552
575
|
declare function isPlatformProviderFactory(value: unknown): value is PlatformProviderFactory;
|
|
553
576
|
declare function validatePlatformProvider(value: unknown, providerType: string): ProviderResult<PlatformProvider>;
|
|
554
577
|
export { PLATFORM_PROVIDER_CONTRACT_VERSION, isPlatformProviderFactory, validatePlatformProvider };
|
|
555
|
-
export type { ChangeRequestSnapshot, CheckLogSnapshot, CheckRunSnapshot, GitEvidenceSnapshot, IssueSnapshot, JsonValue, MilestoneReconciliation, MilestoneDefinition, MilestoneInitialization, LabelDefinition, LabelReconciliation, MutationIdentity, MutationReceipt, PlatformCapabilities, PlatformContextSnapshot, PlatformError, PlatformProvider, PlatformProviderFactory, PlatformProviderFactoryInput, ProviderOperationContext, ProviderResult, ReleaseSnapshot, RemoteCommentSnapshot, RequiredCheckSnapshot, RepositoryMetadataSnapshot, ReleaseNotesFacts, ResourceIdentity, SecurityAlertKind, SecurityAlertSnapshot, ReviewSnapshot, VerificationRemoteFacts };
|
|
578
|
+
export type { ChangeRequestSnapshot, CheckLogSnapshot, CheckRunSnapshot, GitEvidenceSnapshot, IssueSnapshot, JsonValue, MilestoneReconciliation, MilestoneDefinition, MilestoneInitialization, LabelDefinition, LabelReconciliation, MutationIdentity, MutationReceipt, PlatformCapabilities, PlatformContextSnapshot, PlatformError, PlatformProvider, PlatformProviderFactory, PlatformProviderFactoryInput, ProviderOperationContext, ProviderResult, ReleaseSnapshot, RemoteCommentSnapshot, RequiredCheckSnapshot, RepositoryMetadataSnapshot, ReleaseNotesFacts, ReleaseNoteAuthor, ReleaseNoteIssue, ReleaseNotePullRequest, ResourceIdentity, SecurityAlertKind, SecurityAlertSnapshot, ReviewSnapshot, VerificationRemoteFacts };
|