lossless-openclaw-orchestrator 1.1.2 → 1.1.3
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 +1 -1
- package/dist/packages/cli/src/index.js +169 -0
- package/dist/packages/cli/src/runtime-issue-packet.js +357 -0
- package/dist/packages/cli/src/runtime-sweep-summary.js +267 -0
- package/docs/RELEASE_NOTES_1.1.3.md +113 -0
- package/evals/scenarios/v1/failed-runtime-proof-issue-packet.json +52 -0
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/packages/cli/src/index.ts +166 -0
- package/packages/cli/src/runtime-issue-packet.ts +448 -0
- package/packages/cli/src/runtime-sweep-summary.ts +355 -0
- package/packages/openclaw-plugin/openclaw.plugin.json +1 -1
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ safe action without rereading raw transcripts.
|
|
|
14
14
|
[](LICENSE)
|
|
15
15
|
[](CONTRIBUTING.md)
|
|
16
16
|
|
|
17
|
-
[Setup](docs/SETUP.md) · [Contributing](CONTRIBUTING.md) · [Agent Instructions](AGENTS.md) · [Agent Skill](skills/lossless-openclaw-orchestrator/SKILL.md) · [OpenClaw Plugin](docs/OPENCLAW_PLUGIN.md) · [Security](SECURITY.md) · [Code of Conduct](CODE_OF_CONDUCT.md) · [Vision](VISION.md) · [Privacy](docs/PRIVACY.md) · [Claude Boundary](docs/CLAUDE_ADAPTER_BOUNDARY.md) · [Claim Audit](docs/CLAIM_AUDIT.md) · [Release Notes](docs/RELEASE_NOTES_1.1.
|
|
17
|
+
[Setup](docs/SETUP.md) · [Contributing](CONTRIBUTING.md) · [Agent Instructions](AGENTS.md) · [Agent Skill](skills/lossless-openclaw-orchestrator/SKILL.md) · [OpenClaw Plugin](docs/OPENCLAW_PLUGIN.md) · [Security](SECURITY.md) · [Code of Conduct](CODE_OF_CONDUCT.md) · [Vision](VISION.md) · [Privacy](docs/PRIVACY.md) · [Claude Boundary](docs/CLAUDE_ADAPTER_BOUNDARY.md) · [Claim Audit](docs/CLAIM_AUDIT.md) · [Release Notes](docs/RELEASE_NOTES_1.1.3.md) · [1.0 Notes](docs/RELEASE_NOTES_1.0.0.md) · [License](LICENSE)
|
|
18
18
|
|
|
19
19
|
## Why It Matters
|
|
20
20
|
|
|
@@ -16,7 +16,9 @@ import { runOpenClawGatewayLiveControlSmoke } from "./openclaw-live-control-smok
|
|
|
16
16
|
import { runOpenClawPostActionRefreshSmoke } from "./openclaw-post-action-refresh-smoke.js";
|
|
17
17
|
import { createScorecardSweep } from "./scorecard-sweep.js";
|
|
18
18
|
import { createScenarioSweep } from "./scenario-sweep.js";
|
|
19
|
+
import { createRuntimeProofIssuePacket } from "./runtime-issue-packet.js";
|
|
19
20
|
import { createOnboardingStatusReport, writeOnboardingStatusReport } from "./onboarding-status.js";
|
|
21
|
+
import { createRuntimeSweepSummary } from "./runtime-sweep-summary.js";
|
|
20
22
|
import { normalizeReleaseClaimScope } from "./release-claim-scope.js";
|
|
21
23
|
import { AppServerLiveControlSmokeClient, runLiveControlSmoke } from "./live-control-smoke.js";
|
|
22
24
|
import { createLocalMacSearchUiShell, REQUIRED_LOCAL_MAC_SEARCH_UI_TOOLS, sampleLocalMacSearchUiShell, writeLocalMacSearchUiEvidence } from "../../local-mac-ui/src/shell.js";
|
|
@@ -380,6 +382,18 @@ async function main() {
|
|
|
380
382
|
process.exitCode = 1;
|
|
381
383
|
return;
|
|
382
384
|
}
|
|
385
|
+
if (command === "runtime" && args[0] === "sweep-summary") {
|
|
386
|
+
if (hasHelpFlag(args.slice(1))) {
|
|
387
|
+
printRuntimeSweepSummaryHelp();
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
const parsed = parseRuntimeSweepSummaryArgs(args.slice(1));
|
|
391
|
+
const report = createRuntimeSweepSummary(parsed);
|
|
392
|
+
console.log(JSON.stringify(report, null, 2));
|
|
393
|
+
if (parsed.strict && (!report.summaryReady || report.claimBoundary.supportedClaimScope === "none"))
|
|
394
|
+
process.exitCode = 1;
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
383
397
|
if (command === "ui" && args[0] === "local-mac-search") {
|
|
384
398
|
if (hasHelpFlag(args.slice(1))) {
|
|
385
399
|
printLocalMacSearchUiHelp();
|
|
@@ -456,6 +470,25 @@ async function main() {
|
|
|
456
470
|
process.exitCode = 1;
|
|
457
471
|
return;
|
|
458
472
|
}
|
|
473
|
+
if (command === "runtime" && args[0] === "issue-packet") {
|
|
474
|
+
if (hasHelpFlag(args.slice(1))) {
|
|
475
|
+
printRuntimeIssuePacketHelp();
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
const parsed = parseRuntimeIssuePacketArgs(args.slice(1));
|
|
479
|
+
const report = createRuntimeProofIssuePacket({
|
|
480
|
+
evidenceDir: parsed.evidenceDir,
|
|
481
|
+
failureReport: parsed.failureReport,
|
|
482
|
+
parentIssue: parsed.parentIssue,
|
|
483
|
+
operatingLoopIssue: parsed.operatingLoopIssue,
|
|
484
|
+
milestone: parsed.milestone,
|
|
485
|
+
now: parsed.now
|
|
486
|
+
});
|
|
487
|
+
console.log(JSON.stringify(report, null, 2));
|
|
488
|
+
if (parsed.strict && !report.issuePacketReady)
|
|
489
|
+
process.exitCode = 1;
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
459
492
|
if (command === "release" && args[0] === "preflight") {
|
|
460
493
|
if (hasHelpFlag(args.slice(1))) {
|
|
461
494
|
printReleasePreflightHelp();
|
|
@@ -750,9 +783,11 @@ function mainUsageText() {
|
|
|
750
783
|
" loo openclaw live-control-smoke --evidence-dir path --thread-id id [--openclaw-bin path] [--dev] [--profile name] [--gateway-url ws://127.0.0.1:port] [--token token] [--gateway-timeout-ms ms] [--session-key key] [--message text] [--strict]",
|
|
751
784
|
" loo openclaw post-action-refresh-smoke --evidence-dir path --thread-id id --live-proof-report path [--openclaw-bin path] [--dev] [--profile name] [--gateway-url ws://127.0.0.1:port] [--token token] [--gateway-timeout-ms ms] [--session-key key] [--query text] [--expand-profile metadata|brief|evidence] [--token-budget n] [--strict]",
|
|
752
785
|
" loo scorecards sweep --evidence-dir path [--scorecard-dir path] [--claim-scope codex-live-control|codex-read-search-expand-dry-run|codex-working-app-proof] [--strict]",
|
|
786
|
+
" loo runtime sweep-summary --evidence-dir path --dry-run-scenarios path --runtime-scenarios path --scorecard-sweep path --published-smoke path [--runtime-proof-dir path] [--now iso] [--strict]",
|
|
753
787
|
" loo ui local-mac-search --evidence-dir path [--sample] [--strict]",
|
|
754
788
|
" loo eval retrieval --scenario-file path [--evidence-path path] [--strict]",
|
|
755
789
|
" loo eval scenarios --evidence-dir path [--scenario-dir path] [--runtime-proof-dir path] [--strict]",
|
|
790
|
+
" loo runtime issue-packet --evidence-dir path --failure-report path [--parent-issue #n] [--operating-loop #n] [--milestone name] [--now iso] [--strict]",
|
|
756
791
|
" loo release preflight [--evidence-dir path] [--claim-scope codex-live-control|codex-read-search-expand-dry-run|codex-working-app-proof] [--approved-live-control-evidence path] [--runtime-proof-dir path] [--strict]",
|
|
757
792
|
" loo release bundle --evidence-dir path [--claim-scope codex-live-control|codex-read-search-expand-dry-run|codex-working-app-proof] [--approved-live-control-evidence path] [--runtime-proof-dir path] [--strict]",
|
|
758
793
|
" loo release status --evidence-dir path --candidate-sha sha [--claim-scope codex-live-control|codex-read-search-expand-dry-run|codex-working-app-proof] [--approved-live-control-evidence path] [--runtime-proof-dir path] [--npm-publish-approval-evidence path] [--github-release-approval-evidence path] [--github-ci-evidence path] [--codeql-evidence path] [--desktop-gui-required --desktop-gui-approval-evidence path] [--now iso] [--strict]",
|
|
@@ -906,6 +941,48 @@ function printScenarioSweepHelp() {
|
|
|
906
941
|
" It does not read raw Codex transcripts, run live Codex control, mutate a desktop GUI, publish npm, or create a GitHub Release."
|
|
907
942
|
].join("\n"));
|
|
908
943
|
}
|
|
944
|
+
function printRuntimeIssuePacketHelp() {
|
|
945
|
+
console.log([
|
|
946
|
+
"Usage:",
|
|
947
|
+
" loo runtime issue-packet --evidence-dir path --failure-report path [--parent-issue #n] [--operating-loop #n] [--milestone name] [--now iso] [--strict]",
|
|
948
|
+
"",
|
|
949
|
+
"Writes a public-safe issue-ready handoff packet from a failed runtime proof or scenario sweep report.",
|
|
950
|
+
"",
|
|
951
|
+
"Required:",
|
|
952
|
+
" --evidence-dir is required and receives runtime-proof-issue-packet.json.",
|
|
953
|
+
" --failure-report points to the failed public-safe runtime proof, smoke, or scenario-sweep JSON report.",
|
|
954
|
+
"",
|
|
955
|
+
"Strict mode:",
|
|
956
|
+
" --strict exits non-zero when the failure report is missing, malformed, lacks blocker codes, or when packet redaction fails.",
|
|
957
|
+
"",
|
|
958
|
+
"Safety boundary:",
|
|
959
|
+
" The command never runs gh issue create and never writes to GitHub.",
|
|
960
|
+
" It records only blocker codes, scenario ids, duplicate-check query, acceptance criteria, proof boundary, and redaction categories.",
|
|
961
|
+
" It does not read raw Codex transcripts, run live Codex control, mutate a GUI, publish npm, or create a GitHub Release."
|
|
962
|
+
].join("\n"));
|
|
963
|
+
}
|
|
964
|
+
function printRuntimeSweepSummaryHelp() {
|
|
965
|
+
console.log([
|
|
966
|
+
"Usage:",
|
|
967
|
+
" loo runtime sweep-summary --evidence-dir path --dry-run-scenarios path --runtime-scenarios path --scorecard-sweep path --published-smoke path [--runtime-proof-dir path] [--now iso] [--strict]",
|
|
968
|
+
"",
|
|
969
|
+
"Writes a public-safe summary that separates dry-run scenario readiness from missing runtime proof markers.",
|
|
970
|
+
"",
|
|
971
|
+
"Required:",
|
|
972
|
+
" --dry-run-scenarios points to the v1 dry-run scenario sweep report.",
|
|
973
|
+
" --runtime-scenarios points to the v1.1 runtime-required scenario sweep report.",
|
|
974
|
+
" --scorecard-sweep points to the working-app scorecard sweep report.",
|
|
975
|
+
" --published-smoke points to the published-package or gateway setup smoke report.",
|
|
976
|
+
"",
|
|
977
|
+
"Strict mode:",
|
|
978
|
+
" --strict exits non-zero when the summary itself cannot be produced safely or no claim scope is supported.",
|
|
979
|
+
" Missing runtime markers remain claim-boundary blockers, not packet-generation failures.",
|
|
980
|
+
"",
|
|
981
|
+
"Safety boundary:",
|
|
982
|
+
" The command consumes public-safe reports only.",
|
|
983
|
+
" It does not read raw Codex transcripts, run live Codex control, mutate a GUI, publish npm, create tags, or create a GitHub Release."
|
|
984
|
+
].join("\n"));
|
|
985
|
+
}
|
|
909
986
|
function printOnboardingStatusHelp() {
|
|
910
987
|
console.log([
|
|
911
988
|
"Usage:",
|
|
@@ -1640,6 +1717,47 @@ function parseScenarioSweepArgs(input) {
|
|
|
1640
1717
|
throw new Error("eval scenarios requires --evidence-dir");
|
|
1641
1718
|
return { evidenceDir, scenarioDir, runtimeProofDir, scenarioIds: scenarioIds.length ? scenarioIds : undefined, strict };
|
|
1642
1719
|
}
|
|
1720
|
+
function parseRuntimeIssuePacketArgs(input) {
|
|
1721
|
+
let evidenceDir = "";
|
|
1722
|
+
let failureReport = "";
|
|
1723
|
+
let parentIssue;
|
|
1724
|
+
let operatingLoopIssue;
|
|
1725
|
+
let milestone;
|
|
1726
|
+
let now;
|
|
1727
|
+
let strict = false;
|
|
1728
|
+
for (let index = 0; index < input.length; index += 1) {
|
|
1729
|
+
const arg = input[index];
|
|
1730
|
+
if (arg === "--evidence-dir") {
|
|
1731
|
+
evidenceDir = requireOptionValue(input[++index], arg);
|
|
1732
|
+
}
|
|
1733
|
+
else if (arg === "--failure-report") {
|
|
1734
|
+
failureReport = requireOptionValue(input[++index], arg);
|
|
1735
|
+
}
|
|
1736
|
+
else if (arg === "--parent-issue") {
|
|
1737
|
+
parentIssue = requireOptionValue(input[++index], arg);
|
|
1738
|
+
}
|
|
1739
|
+
else if (arg === "--operating-loop") {
|
|
1740
|
+
operatingLoopIssue = requireOptionValue(input[++index], arg);
|
|
1741
|
+
}
|
|
1742
|
+
else if (arg === "--milestone") {
|
|
1743
|
+
milestone = requireOptionValue(input[++index], arg);
|
|
1744
|
+
}
|
|
1745
|
+
else if (arg === "--now") {
|
|
1746
|
+
now = requireOptionValue(input[++index], arg);
|
|
1747
|
+
}
|
|
1748
|
+
else if (arg === "--strict") {
|
|
1749
|
+
strict = true;
|
|
1750
|
+
}
|
|
1751
|
+
else {
|
|
1752
|
+
throw new Error(`Unknown runtime issue-packet option: ${arg}`);
|
|
1753
|
+
}
|
|
1754
|
+
}
|
|
1755
|
+
if (!evidenceDir)
|
|
1756
|
+
throw new Error("runtime issue-packet requires --evidence-dir");
|
|
1757
|
+
if (!failureReport)
|
|
1758
|
+
throw new Error("runtime issue-packet requires --failure-report");
|
|
1759
|
+
return { evidenceDir, failureReport, parentIssue, operatingLoopIssue, milestone, now, strict };
|
|
1760
|
+
}
|
|
1643
1761
|
function readRetrievalScenarioFile(path) {
|
|
1644
1762
|
const scenarioPath = resolve(path);
|
|
1645
1763
|
if (!existsSync(scenarioPath))
|
|
@@ -2066,6 +2184,57 @@ function parseScorecardSweepArgs(input) {
|
|
|
2066
2184
|
throw new Error("scorecards sweep requires --evidence-dir");
|
|
2067
2185
|
return { evidenceDir, scorecardDir, claimScope, strict };
|
|
2068
2186
|
}
|
|
2187
|
+
function parseRuntimeSweepSummaryArgs(input) {
|
|
2188
|
+
let evidenceDir;
|
|
2189
|
+
let dryRunScenarios;
|
|
2190
|
+
let runtimeScenarios;
|
|
2191
|
+
let scorecardSweep;
|
|
2192
|
+
let publishedSmoke;
|
|
2193
|
+
let runtimeProofDir;
|
|
2194
|
+
let now;
|
|
2195
|
+
let strict = false;
|
|
2196
|
+
for (let index = 0; index < input.length; index += 1) {
|
|
2197
|
+
const arg = input[index];
|
|
2198
|
+
if (arg === "--evidence-dir") {
|
|
2199
|
+
evidenceDir = requireOptionValue(input[++index], arg);
|
|
2200
|
+
}
|
|
2201
|
+
else if (arg === "--dry-run-scenarios") {
|
|
2202
|
+
dryRunScenarios = requireOptionValue(input[++index], arg);
|
|
2203
|
+
}
|
|
2204
|
+
else if (arg === "--runtime-scenarios") {
|
|
2205
|
+
runtimeScenarios = requireOptionValue(input[++index], arg);
|
|
2206
|
+
}
|
|
2207
|
+
else if (arg === "--scorecard-sweep") {
|
|
2208
|
+
scorecardSweep = requireOptionValue(input[++index], arg);
|
|
2209
|
+
}
|
|
2210
|
+
else if (arg === "--published-smoke") {
|
|
2211
|
+
publishedSmoke = requireOptionValue(input[++index], arg);
|
|
2212
|
+
}
|
|
2213
|
+
else if (arg === "--runtime-proof-dir") {
|
|
2214
|
+
runtimeProofDir = requireOptionValue(input[++index], arg);
|
|
2215
|
+
}
|
|
2216
|
+
else if (arg === "--now") {
|
|
2217
|
+
now = requireOptionValue(input[++index], arg);
|
|
2218
|
+
}
|
|
2219
|
+
else if (arg === "--strict") {
|
|
2220
|
+
strict = true;
|
|
2221
|
+
}
|
|
2222
|
+
else {
|
|
2223
|
+
throw new Error(`Unknown runtime sweep-summary option: ${arg}`);
|
|
2224
|
+
}
|
|
2225
|
+
}
|
|
2226
|
+
if (!evidenceDir)
|
|
2227
|
+
throw new Error("runtime sweep-summary requires --evidence-dir");
|
|
2228
|
+
if (!dryRunScenarios)
|
|
2229
|
+
throw new Error("runtime sweep-summary requires --dry-run-scenarios");
|
|
2230
|
+
if (!runtimeScenarios)
|
|
2231
|
+
throw new Error("runtime sweep-summary requires --runtime-scenarios");
|
|
2232
|
+
if (!scorecardSweep)
|
|
2233
|
+
throw new Error("runtime sweep-summary requires --scorecard-sweep");
|
|
2234
|
+
if (!publishedSmoke)
|
|
2235
|
+
throw new Error("runtime sweep-summary requires --published-smoke");
|
|
2236
|
+
return { evidenceDir, dryRunScenarios, runtimeScenarios, scorecardSweep, publishedSmoke, runtimeProofDir, now, strict };
|
|
2237
|
+
}
|
|
2069
2238
|
function parsePositiveInteger(value, name, max) {
|
|
2070
2239
|
const parsed = Number(value);
|
|
2071
2240
|
if (!Number.isInteger(parsed) || parsed < 1 || (max !== undefined && parsed > max)) {
|
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, realpathSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { basename, join, resolve } from "node:path";
|
|
3
|
+
const DEFAULT_LABELS = ["enhancement", "safety", "orchestrator", "eval"];
|
|
4
|
+
const DEFAULT_PARENT_REFS = ["#309", "#16"];
|
|
5
|
+
const SECRET_LIKE_PATTERN = /(npm_[A-Za-z0-9]{20,}|Bearer\s+[A-Za-z0-9._-]{20,}|sk-[A-Za-z0-9]{20,}|github_pat_[A-Za-z0-9_]{20,}|gh[pousr]_[A-Za-z0-9_]{20,}|-----BEGIN [A-Z ]*PRIVATE KEY-----)/g;
|
|
6
|
+
const RAW_TRANSCRIPT_PATH_PATTERN = /(?:~|\/[^\s"'`]*)\/\.codex\/(?:sessions|archived_sessions)\/[^\s"'`]+|\b[\w.-]+\.jsonl(?:\.gz)?\b/g;
|
|
7
|
+
const SQLITE_ARTIFACT_PATTERN = /\b[\w.-]+\.(?:sqlite|sqlite-wal|sqlite-shm|db|db-journal|db-wal|db-shm)\b/g;
|
|
8
|
+
const SCREENSHOT_PATTERN = /\b[\w.-]+\.(?:png|jpg|jpeg|webp|heic|gif|tiff|mov|mp4|m4v|webm)\b/gi;
|
|
9
|
+
export function createRuntimeProofIssuePacket(options) {
|
|
10
|
+
const evidenceDir = resolve(options.evidenceDir);
|
|
11
|
+
const failureReportPath = resolve(options.failureReport);
|
|
12
|
+
const evidenceDirRejected = hasPrivateFinding(evidenceDir, "raw_transcript_path");
|
|
13
|
+
const packetPath = evidenceDirRejected ? "not_written:evidence_dir_transcript_path_rejected" : join(evidenceDir, "runtime-proof-issue-packet.json");
|
|
14
|
+
if (!evidenceDirRejected)
|
|
15
|
+
mkdirSync(evidenceDir, { recursive: true });
|
|
16
|
+
const generatedAtResult = normalizeGeneratedAt(options.now);
|
|
17
|
+
const generatedAt = generatedAtResult.value;
|
|
18
|
+
const explicitParentRefs = [
|
|
19
|
+
normalizeIssueRef(options.parentIssue),
|
|
20
|
+
normalizeIssueRef(options.operatingLoopIssue)
|
|
21
|
+
].filter(Boolean);
|
|
22
|
+
const parentRefs = uniqueStrings(explicitParentRefs.length > 0 ? explicitParentRefs : DEFAULT_PARENT_REFS);
|
|
23
|
+
const sourceMissing = !existsSync(failureReportPath);
|
|
24
|
+
const resolvedFailureReportPath = sourceMissing ? failureReportPath : safeRealpath(failureReportPath);
|
|
25
|
+
const transcriptPathRejected = !sourceMissing && (hasPrivateFinding(failureReportPath, "raw_transcript_path") ||
|
|
26
|
+
hasPrivateFinding(resolvedFailureReportPath, "raw_transcript_path"));
|
|
27
|
+
const sourceText = !sourceMissing && !transcriptPathRejected ? readFileSync(resolvedFailureReportPath, "utf8") : "";
|
|
28
|
+
const inputFindings = scanTextForPrivateFindings(sourceText);
|
|
29
|
+
const parsed = readJsonObject(sourceText);
|
|
30
|
+
const invalidJson = !sourceMissing && !transcriptPathRejected && !parsed;
|
|
31
|
+
const blockerCodes = sourceMissing
|
|
32
|
+
? ["failure_report_missing"]
|
|
33
|
+
: transcriptPathRejected
|
|
34
|
+
? ["failure_report_transcript_path_rejected"]
|
|
35
|
+
: parsed
|
|
36
|
+
? extractBlockerCodes(parsed)
|
|
37
|
+
: ["failure_report_invalid_json"];
|
|
38
|
+
const scenarioIds = parsed ? extractScenarioIds(parsed) : [];
|
|
39
|
+
const rawClaimScope = parsed ? stringField(parsed, "claimScope") ?? stringField(parsed, "claim_scope") : null;
|
|
40
|
+
const claimScope = rawClaimScope ? safePublicCode(rawClaimScope) : null;
|
|
41
|
+
const primaryBlocker = blockerCodes[0] ?? "runtime_proof_failure";
|
|
42
|
+
const title = `Runtime proof failed: ${safeTitleSegment(primaryBlocker)}`;
|
|
43
|
+
const labels = uniqueStrings([
|
|
44
|
+
...DEFAULT_LABELS,
|
|
45
|
+
...(scenarioIds.some((id) => /codex|gateway|desktop/i.test(id)) || blockerCodes.some((blocker) => /codex|gateway|desktop/i.test(blocker)) ? ["codex"] : [])
|
|
46
|
+
]);
|
|
47
|
+
const duplicateCheckQuery = buildDuplicateCheckQuery(title, primaryBlocker);
|
|
48
|
+
const evidencePath = publicEvidencePath(evidenceDir);
|
|
49
|
+
const steps = [
|
|
50
|
+
"Run the relevant LCO runtime proof or scenario sweep with a public-safe evidence directory.",
|
|
51
|
+
"Inspect the sanitized failure report and blocker codes.",
|
|
52
|
+
"Open or update a GitHub issue only after duplicate-check review and maintainer approval.",
|
|
53
|
+
"Attach public-safe evidence links only; do not paste raw gateway output, raw prompts, raw transcripts, screenshots, SQLite DB contents, tokens, cookies, or credentials."
|
|
54
|
+
];
|
|
55
|
+
const expected = "Runtime proof markers satisfy the claimed scenario, or the failure is converted into a public-safe issue handoff with exact blocker codes and acceptance criteria.";
|
|
56
|
+
const actual = sourceMissing
|
|
57
|
+
? "No failure report was available for packet generation."
|
|
58
|
+
: transcriptPathRejected
|
|
59
|
+
? "The failure report path looked like a raw Codex transcript path and was rejected before reading."
|
|
60
|
+
: invalidJson
|
|
61
|
+
? "The failure report was not valid JSON; only sanitized category-level findings were retained."
|
|
62
|
+
: `Runtime proof failed with blocker codes: ${blockerCodes.join(", ") || "none reported"}.`;
|
|
63
|
+
const acceptanceCriteria = [
|
|
64
|
+
"Reproduce the failed runtime proof or scenario sweep from the public-safe command and evidence path.",
|
|
65
|
+
"Resolve or explicitly defer each blocker code listed in this packet.",
|
|
66
|
+
"Record a new public-safe proof marker or a new fail-closed issue packet after the fix.",
|
|
67
|
+
"Keep external GitHub writes manual or approval-gated; this packet alone must not create issues.",
|
|
68
|
+
"Verify the final packet contains no raw transcript text, raw transcript paths, screenshots, SQLite DBs, tokens, cookies, credentials, or private customer data."
|
|
69
|
+
];
|
|
70
|
+
const proofBoundary = "This packet is a public-safe GitHub issue handoff for failed runtime proof only. It does not create GitHub issues, mutate external systems, run live Codex control, mutate a GUI, publish npm, or create a GitHub Release.";
|
|
71
|
+
const issueBody = buildIssueBody({
|
|
72
|
+
parentRefs,
|
|
73
|
+
evidencePath,
|
|
74
|
+
scenarioIds,
|
|
75
|
+
blockerCodes,
|
|
76
|
+
steps,
|
|
77
|
+
expected,
|
|
78
|
+
actual,
|
|
79
|
+
proofBoundary,
|
|
80
|
+
acceptanceCriteria,
|
|
81
|
+
duplicateCheckQuery
|
|
82
|
+
});
|
|
83
|
+
const initialReport = {
|
|
84
|
+
kind: "loo_runtime_proof_issue_packet",
|
|
85
|
+
ok: false,
|
|
86
|
+
issuePacketReady: false,
|
|
87
|
+
generatedAt,
|
|
88
|
+
packetPath,
|
|
89
|
+
title,
|
|
90
|
+
labels,
|
|
91
|
+
milestone: options.milestone?.trim() || null,
|
|
92
|
+
parentRefs,
|
|
93
|
+
duplicateCheckQuery,
|
|
94
|
+
steps,
|
|
95
|
+
expected,
|
|
96
|
+
actual,
|
|
97
|
+
proofBoundary,
|
|
98
|
+
acceptanceCriteria,
|
|
99
|
+
evidencePath,
|
|
100
|
+
issueBody,
|
|
101
|
+
source: {
|
|
102
|
+
failureReportPath: redactPrivateSpans(failureReportPath),
|
|
103
|
+
claimScope,
|
|
104
|
+
scenarioIds,
|
|
105
|
+
blockerCodes,
|
|
106
|
+
inputFindings
|
|
107
|
+
},
|
|
108
|
+
redactionScan: {
|
|
109
|
+
publicSafe: true,
|
|
110
|
+
rawSecretIncluded: false,
|
|
111
|
+
rawTranscriptPathIncluded: false,
|
|
112
|
+
sqliteIncluded: false,
|
|
113
|
+
screenshotOrVideoIncluded: false,
|
|
114
|
+
findings: []
|
|
115
|
+
},
|
|
116
|
+
actionsPerformed: {
|
|
117
|
+
githubIssueCreated: false,
|
|
118
|
+
externalWrite: false,
|
|
119
|
+
liveCodexControlRun: false,
|
|
120
|
+
desktopGuiActionRun: false,
|
|
121
|
+
rawTranscriptRead: false
|
|
122
|
+
},
|
|
123
|
+
privateDataExclusions: [
|
|
124
|
+
"raw gateway output",
|
|
125
|
+
"raw Codex transcripts",
|
|
126
|
+
"raw prompts or transcript spans",
|
|
127
|
+
"absolute transcript paths",
|
|
128
|
+
"SQLite DBs",
|
|
129
|
+
"screenshots or videos",
|
|
130
|
+
"tokens, credentials, API keys, cookies",
|
|
131
|
+
"private customer data"
|
|
132
|
+
],
|
|
133
|
+
blockers: [
|
|
134
|
+
...(evidenceDirRejected ? ["evidence_dir_transcript_path_rejected"] : []),
|
|
135
|
+
...(generatedAtResult.invalid ? ["invalid_generated_at"] : []),
|
|
136
|
+
...(sourceMissing ? ["failure_report_missing"] : []),
|
|
137
|
+
...(transcriptPathRejected ? ["failure_report_transcript_path_rejected"] : []),
|
|
138
|
+
...(invalidJson ? ["failure_report_invalid_json"] : []),
|
|
139
|
+
...(!sourceMissing && !transcriptPathRejected && !invalidJson && blockerCodes.length === 0 ? ["failure_report_blockers_missing"] : [])
|
|
140
|
+
],
|
|
141
|
+
nextAction: ""
|
|
142
|
+
};
|
|
143
|
+
const outputFindings = scanTextForPrivateFindings(JSON.stringify(initialReport));
|
|
144
|
+
const redactionScan = {
|
|
145
|
+
publicSafe: outputFindings.length === 0,
|
|
146
|
+
rawSecretIncluded: outputFindings.some((finding) => finding.reason === "secret_like_value"),
|
|
147
|
+
rawTranscriptPathIncluded: outputFindings.some((finding) => finding.reason === "raw_transcript_path"),
|
|
148
|
+
sqliteIncluded: outputFindings.some((finding) => finding.reason === "sqlite_artifact"),
|
|
149
|
+
screenshotOrVideoIncluded: outputFindings.some((finding) => finding.reason === "screenshot_or_video"),
|
|
150
|
+
findings: outputFindings
|
|
151
|
+
};
|
|
152
|
+
const blockers = [
|
|
153
|
+
...initialReport.blockers,
|
|
154
|
+
...(redactionScan.publicSafe ? [] : ["issue_packet_redaction_failed"])
|
|
155
|
+
];
|
|
156
|
+
const report = {
|
|
157
|
+
...initialReport,
|
|
158
|
+
ok: blockers.length === 0,
|
|
159
|
+
issuePacketReady: blockers.length === 0,
|
|
160
|
+
redactionScan,
|
|
161
|
+
blockers,
|
|
162
|
+
nextAction: blockers.length === 0
|
|
163
|
+
? "Review the duplicate-check query, then manually create or update the GitHub issue with this public-safe packet."
|
|
164
|
+
: "Repair the failure report input or packet redaction blockers before filing an issue."
|
|
165
|
+
};
|
|
166
|
+
const persistedReport = redactionScan.publicSafe ? report : createRedactionFailureStub(report, redactionScan, blockers);
|
|
167
|
+
if (!evidenceDirRejected)
|
|
168
|
+
writeFileSync(packetPath, `${JSON.stringify(persistedReport, null, 2)}\n`);
|
|
169
|
+
return persistedReport;
|
|
170
|
+
}
|
|
171
|
+
function readJsonObject(text) {
|
|
172
|
+
try {
|
|
173
|
+
const parsed = JSON.parse(text);
|
|
174
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
function normalizeGeneratedAt(value) {
|
|
181
|
+
if (!value)
|
|
182
|
+
return { value: new Date().toISOString(), invalid: false };
|
|
183
|
+
const parsed = new Date(value);
|
|
184
|
+
if (!Number.isFinite(parsed.getTime()))
|
|
185
|
+
return { value: new Date().toISOString(), invalid: true };
|
|
186
|
+
const normalized = parsed.toISOString();
|
|
187
|
+
return { value: normalized, invalid: normalized !== value };
|
|
188
|
+
}
|
|
189
|
+
function publicEvidencePath(evidenceDir) {
|
|
190
|
+
return `local-evidence-dir:${safeCode(basename(evidenceDir) || "evidence")}`;
|
|
191
|
+
}
|
|
192
|
+
function safeRealpath(path) {
|
|
193
|
+
try {
|
|
194
|
+
return realpathSync(path);
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
return path;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
function createRedactionFailureStub(report, redactionScan, blockers) {
|
|
201
|
+
return {
|
|
202
|
+
...report,
|
|
203
|
+
ok: false,
|
|
204
|
+
issuePacketReady: false,
|
|
205
|
+
title: "Runtime proof packet redaction failed",
|
|
206
|
+
milestone: null,
|
|
207
|
+
duplicateCheckQuery: "",
|
|
208
|
+
steps: [],
|
|
209
|
+
expected: "A runtime proof issue packet must be public-safe before it is persisted.",
|
|
210
|
+
actual: "The generated packet failed its final redaction scan; unsafe fields were replaced by this minimal fail-closed stub.",
|
|
211
|
+
acceptanceCriteria: [],
|
|
212
|
+
issueBody: "",
|
|
213
|
+
source: {
|
|
214
|
+
failureReportPath: redactPrivateSpans(report.source.failureReportPath),
|
|
215
|
+
claimScope: null,
|
|
216
|
+
scenarioIds: [],
|
|
217
|
+
blockerCodes: [],
|
|
218
|
+
inputFindings: report.source.inputFindings
|
|
219
|
+
},
|
|
220
|
+
redactionScan,
|
|
221
|
+
blockers,
|
|
222
|
+
nextAction: "Repair the failure report input or packet redaction blockers before filing an issue."
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
function scanTextForPrivateFindings(text) {
|
|
226
|
+
return [
|
|
227
|
+
countFinding("secret_like_value", text.match(SECRET_LIKE_PATTERN)?.length ?? 0),
|
|
228
|
+
countFinding("raw_transcript_path", text.match(RAW_TRANSCRIPT_PATH_PATTERN)?.length ?? 0),
|
|
229
|
+
countFinding("sqlite_artifact", text.match(SQLITE_ARTIFACT_PATTERN)?.length ?? 0),
|
|
230
|
+
countFinding("screenshot_or_video", text.match(SCREENSHOT_PATTERN)?.length ?? 0)
|
|
231
|
+
].filter((finding) => Boolean(finding));
|
|
232
|
+
}
|
|
233
|
+
function hasPrivateFinding(text, reason) {
|
|
234
|
+
return scanTextForPrivateFindings(text).some((finding) => finding.reason === reason);
|
|
235
|
+
}
|
|
236
|
+
function countFinding(reason, count) {
|
|
237
|
+
return count > 0 ? { reason, count } : null;
|
|
238
|
+
}
|
|
239
|
+
function extractBlockerCodes(report) {
|
|
240
|
+
return uniqueStrings([
|
|
241
|
+
...stringArrayField(report, "blockers"),
|
|
242
|
+
...stringArrayField(report, "setupBlockers"),
|
|
243
|
+
...stringArrayField(report, "rawEvidenceBlockers"),
|
|
244
|
+
...extractScenarioBlockers(report),
|
|
245
|
+
stringField(report, "blocker")
|
|
246
|
+
].filter(Boolean)).map((blocker) => safePublicCode(blocker));
|
|
247
|
+
}
|
|
248
|
+
function extractScenarioBlockers(report) {
|
|
249
|
+
const scenarios = Array.isArray(report.scenarios) ? report.scenarios : [];
|
|
250
|
+
return scenarios.flatMap((scenario) => {
|
|
251
|
+
if (!scenario || typeof scenario !== "object" || Array.isArray(scenario))
|
|
252
|
+
return [];
|
|
253
|
+
return stringArrayField(scenario, "blockers");
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
function extractScenarioIds(report) {
|
|
257
|
+
const scenarios = Array.isArray(report.scenarios) ? report.scenarios : [];
|
|
258
|
+
return uniqueStrings([
|
|
259
|
+
stringField(report, "scenario_id"),
|
|
260
|
+
stringField(report, "scenarioId"),
|
|
261
|
+
stringField(report, "id"),
|
|
262
|
+
...scenarios.flatMap((scenario) => {
|
|
263
|
+
if (!scenario || typeof scenario !== "object" || Array.isArray(scenario))
|
|
264
|
+
return [];
|
|
265
|
+
return [
|
|
266
|
+
stringField(scenario, "id"),
|
|
267
|
+
stringField(scenario, "scenario_id"),
|
|
268
|
+
stringField(scenario, "scenarioId")
|
|
269
|
+
];
|
|
270
|
+
})
|
|
271
|
+
].filter(Boolean)).map((id) => safePublicCode(id));
|
|
272
|
+
}
|
|
273
|
+
function buildDuplicateCheckQuery(title, primaryBlocker) {
|
|
274
|
+
return `repo:100yenadmin/Lossless-Codex-Orchestrator-LCO is:issue is:open "${safeQueryPhrase(primaryBlocker)}" "${safeQueryPhrase(title)}"`;
|
|
275
|
+
}
|
|
276
|
+
function buildIssueBody(input) {
|
|
277
|
+
return [
|
|
278
|
+
`Parent: ${input.parentRefs.join(" / ")}`,
|
|
279
|
+
"",
|
|
280
|
+
"## Summary",
|
|
281
|
+
"",
|
|
282
|
+
"A runtime proof or scenario sweep failed and has been converted into a public-safe issue handoff packet.",
|
|
283
|
+
"",
|
|
284
|
+
"## Duplicate Check",
|
|
285
|
+
"",
|
|
286
|
+
`- Query: \`${input.duplicateCheckQuery}\``,
|
|
287
|
+
"",
|
|
288
|
+
"## Evidence",
|
|
289
|
+
"",
|
|
290
|
+
`- Evidence path: \`${input.evidencePath}\``,
|
|
291
|
+
`- Scenario ids: ${input.scenarioIds.length > 0 ? input.scenarioIds.map((id) => `\`${id}\``).join(", ") : "`unknown`"}`,
|
|
292
|
+
`- Blockers: ${input.blockerCodes.length > 0 ? input.blockerCodes.map((code) => `\`${code}\``).join(", ") : "`none reported`"}`,
|
|
293
|
+
"",
|
|
294
|
+
"## Steps",
|
|
295
|
+
"",
|
|
296
|
+
...input.steps.map((step) => `- ${step}`),
|
|
297
|
+
"",
|
|
298
|
+
"## Expected",
|
|
299
|
+
"",
|
|
300
|
+
input.expected,
|
|
301
|
+
"",
|
|
302
|
+
"## Actual",
|
|
303
|
+
"",
|
|
304
|
+
input.actual,
|
|
305
|
+
"",
|
|
306
|
+
"## Acceptance Criteria",
|
|
307
|
+
"",
|
|
308
|
+
...input.acceptanceCriteria.map((criterion) => `- ${criterion}`),
|
|
309
|
+
"",
|
|
310
|
+
"## Proof Boundary",
|
|
311
|
+
"",
|
|
312
|
+
input.proofBoundary,
|
|
313
|
+
""
|
|
314
|
+
].join("\n");
|
|
315
|
+
}
|
|
316
|
+
function stringField(record, field) {
|
|
317
|
+
const value = record?.[field];
|
|
318
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
319
|
+
}
|
|
320
|
+
function stringArrayField(record, field) {
|
|
321
|
+
const value = record[field];
|
|
322
|
+
if (!Array.isArray(value))
|
|
323
|
+
return [];
|
|
324
|
+
return value.filter((entry) => typeof entry === "string" && Boolean(entry.trim())).map((entry) => entry.trim());
|
|
325
|
+
}
|
|
326
|
+
function normalizeIssueRef(value) {
|
|
327
|
+
if (!value)
|
|
328
|
+
return null;
|
|
329
|
+
const trimmed = value.trim();
|
|
330
|
+
if (/^#\d+$/.test(trimmed))
|
|
331
|
+
return trimmed;
|
|
332
|
+
if (/^\d+$/.test(trimmed))
|
|
333
|
+
return `#${trimmed}`;
|
|
334
|
+
return null;
|
|
335
|
+
}
|
|
336
|
+
function uniqueStrings(values) {
|
|
337
|
+
return [...new Set(values.filter(Boolean))];
|
|
338
|
+
}
|
|
339
|
+
function safeCode(value) {
|
|
340
|
+
return value.replace(/[^A-Za-z0-9_:#./-]/g, "_").slice(0, 180);
|
|
341
|
+
}
|
|
342
|
+
function safePublicCode(value) {
|
|
343
|
+
return safeCode(redactPrivateSpans(value));
|
|
344
|
+
}
|
|
345
|
+
function safeTitleSegment(value) {
|
|
346
|
+
return safeCode(value).replace(/_/g, " ").slice(0, 120).trim() || "runtime proof failure";
|
|
347
|
+
}
|
|
348
|
+
function safeQueryPhrase(value) {
|
|
349
|
+
return redactPrivateSpans(value).replace(/["`$\\]/g, "").slice(0, 140);
|
|
350
|
+
}
|
|
351
|
+
function redactPrivateSpans(value) {
|
|
352
|
+
return value
|
|
353
|
+
.replace(SECRET_LIKE_PATTERN, "redacted_secret_like_value")
|
|
354
|
+
.replace(RAW_TRANSCRIPT_PATH_PATTERN, "redacted_raw_transcript_path")
|
|
355
|
+
.replace(SQLITE_ARTIFACT_PATTERN, "redacted_sqlite_artifact")
|
|
356
|
+
.replace(SCREENSHOT_PATTERN, "redacted_media_artifact");
|
|
357
|
+
}
|