@awak-app/simy-cli 0.5.15 → 0.5.17
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 +78 -15
- package/package.json +2 -2
- package/src/agent.js +33 -1
- package/src/cli-contract.js +1 -1
- package/src/codex-plugins/simy/.codex-plugin/plugin.json +5 -6
- package/src/codex-plugins/simy/hooks/README.md +17 -0
- package/src/codex-plugins/simy/hooks/connection-reminder.mjs +184 -0
- package/src/codex-plugins/simy/hooks/hooks.json +27 -0
- package/src/connection-discovery.js +49 -0
- package/src/console/app.js +2 -2
- package/src/orchestrator/audit.js +47 -5
- package/src/orchestrator/budget.js +1 -1
- package/src/orchestrator/checklist-continuation.js +21 -0
- package/src/orchestrator/completion-contract.js +1 -1
- package/src/orchestrator/contract.js +2 -0
- package/src/{codex-plugins/simy/skills/agentic-delivery-loop/SKILL.md → orchestrator/delivery/WORKFLOW.md} +121 -13
- package/src/{codex-plugins/simy/skills/agentic-delivery-loop → orchestrator/delivery}/references/acceptance-evidence.md +27 -3
- package/src/{codex-plugins/simy/skills/agentic-delivery-loop → orchestrator/delivery}/references/change-boundary-matrix.md +1 -1
- package/src/{codex-plugins/simy/skills/agentic-delivery-loop → orchestrator/delivery}/references/delivery-levels.md +78 -27
- package/src/{codex-plugins/simy/skills/agentic-delivery-loop → orchestrator/delivery}/references/minimum-completion.md +3 -3
- package/src/orchestrator/delivery/references/pr-closure.md +203 -0
- package/src/{codex-plugins/simy/skills/agentic-delivery-loop → orchestrator/delivery}/references/state-and-receipts.md +4 -1
- package/src/orchestrator/delivery/references/ux-specification.md +98 -0
- package/src/{codex-plugins/simy/skills/agentic-delivery-loop → orchestrator/delivery}/scripts/production-contract.mjs +1 -1
- package/src/orchestrator/delivery-level.js +19 -0
- package/src/orchestrator/evidence.js +64 -5
- package/src/orchestrator/independent-audit.js +18 -0
- package/src/orchestrator/index.js +7 -0
- package/src/orchestrator/instruction.js +32 -3
- package/src/orchestrator/loop.js +4 -1
- package/src/orchestrator/minimum-completion.js +2 -2
- package/src/orchestrator/pr-closure.js +26 -0
- package/src/orchestrator/pr-preparation.js +420 -0
- package/src/orchestrator/presentation.js +2 -2
- package/src/orchestrator/result.js +8 -2
- package/src/orchestrator/ux-specification.js +20 -0
- package/src/runner.js +104 -1
- package/src/sqm/agent-skill.js +39 -7
- package/src/codex-plugins/simy/skills/agentic-delivery-loop/agents/openai.yaml +0 -5
- /package/src/{codex-plugins/simy/skills/agentic-delivery-loop → orchestrator/delivery}/references/chrome-user-verification.md +0 -0
- /package/src/{codex-plugins/simy/skills/agentic-delivery-loop → orchestrator/delivery}/references/cross-repository-control.md +0 -0
- /package/src/{codex-plugins/simy/skills/agentic-delivery-loop → orchestrator/delivery}/references/local-sqm-evidence.md +0 -0
- /package/src/{codex-plugins/simy/skills/agentic-delivery-loop → orchestrator/delivery}/references/shared-system-specifications.md +0 -0
- /package/src/{codex-plugins/simy/skills/agentic-delivery-loop → orchestrator/delivery}/scripts/check-acceptance.mjs +0 -0
- /package/src/{codex-plugins/simy/skills/agentic-delivery-loop → orchestrator/delivery}/scripts/check-minimum-completion.mjs +0 -0
package/src/runner.js
CHANGED
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
redactExecutionText,
|
|
20
20
|
} from "./orchestrator/execution-io.js";
|
|
21
21
|
import { summarizeCodingLoopEvent } from "./orchestrator/presentation.js";
|
|
22
|
+
import { PR_PREPARATION_CHECKS } from "./orchestrator/pr-preparation.js";
|
|
22
23
|
import { increaseProviderTokenBudget, refreshBudgetState } from "./orchestrator/budget.js";
|
|
23
24
|
import { appendEvent } from "./orchestrator/shared.js";
|
|
24
25
|
import {
|
|
@@ -73,6 +74,7 @@ const INTERRUPTED_STATES = new Set([
|
|
|
73
74
|
"re_instructing",
|
|
74
75
|
]);
|
|
75
76
|
const RESTORABLE_STATES = new Set([...RESUMABLE_STATES, ...INTERRUPTED_STATES]);
|
|
77
|
+
const PR_PREPARATION_IDS = new Set(PR_PREPARATION_CHECKS.map((row) => row.id));
|
|
76
78
|
|
|
77
79
|
export { LocalRunRegistry };
|
|
78
80
|
|
|
@@ -530,6 +532,18 @@ async function runLocalCodingRun(
|
|
|
530
532
|
|
|
531
533
|
markAttachmentsDelivered(run.request.attachments);
|
|
532
534
|
|
|
535
|
+
// All collectors and the executor must use the same root. Bind a missing
|
|
536
|
+
// default only after resolving the authorized checkout, including on resume.
|
|
537
|
+
if (!run.snapshot.charter.ui_evidence_root) {
|
|
538
|
+
const evidenceRoot = path.join(repositoryPath, ".artifacts");
|
|
539
|
+
run.snapshot.charter.ui_evidence_root = evidenceRoot;
|
|
540
|
+
run.request.ui_evidence_root = evidenceRoot;
|
|
541
|
+
appendEvent(run.snapshot, run.status, "Local evidence root bound to the verified checkout.", {
|
|
542
|
+
code: "local_evidence_root_bound",
|
|
543
|
+
});
|
|
544
|
+
await updateRun(run, run.status);
|
|
545
|
+
}
|
|
546
|
+
|
|
533
547
|
const executor =
|
|
534
548
|
executeAttempt ||
|
|
535
549
|
((context) =>
|
|
@@ -1007,9 +1021,90 @@ function redactedAttemptForLedger(attempt, attachments) {
|
|
|
1007
1021
|
},
|
|
1008
1022
|
raw_output: structuredResultForLedger(attempt.raw_output),
|
|
1009
1023
|
observed_evidence: observedEvidenceForLedger(attempt.observed_evidence),
|
|
1024
|
+
pr_preparation: prPreparationForLedger(attempt.pr_preparation),
|
|
1025
|
+
skipped_checks: skippedChecksForLedger(attempt.skipped_checks),
|
|
1010
1026
|
};
|
|
1011
1027
|
}
|
|
1012
1028
|
|
|
1029
|
+
function prPreparationForLedger(value) {
|
|
1030
|
+
return (Array.isArray(value) ? value : []).map((row) => ({
|
|
1031
|
+
id: PR_PREPARATION_IDS.has(row?.id) ? row.id : "unrecognized",
|
|
1032
|
+
applicability: row?.applicability || null,
|
|
1033
|
+
passed: row?.passed === true,
|
|
1034
|
+
observation_present: Boolean(row?.observation),
|
|
1035
|
+
reason_present: Boolean(row?.reason),
|
|
1036
|
+
authoritative_source_present: Boolean(row?.authoritative_source),
|
|
1037
|
+
evidence_ref_count: Array.isArray(row?.evidence_refs) ? row.evidence_refs.length : 0,
|
|
1038
|
+
bound_revisions: validatedHashesForLedger(row?.bound_revisions, 40),
|
|
1039
|
+
companion_revisions: (Array.isArray(row?.companion_revisions) ? row.companion_revisions : [])
|
|
1040
|
+
.map((item) => ({
|
|
1041
|
+
repository_present: Boolean(item?.repository),
|
|
1042
|
+
sha: validatedHashForLedger(item?.sha, 40),
|
|
1043
|
+
})),
|
|
1044
|
+
manifest_revisions: (Array.isArray(row?.manifest_revisions) ? row.manifest_revisions : [])
|
|
1045
|
+
.map((item) => ({
|
|
1046
|
+
manifest_present: Boolean(item?.manifest),
|
|
1047
|
+
sha256: validatedHashForLedger(item?.sha256, 64),
|
|
1048
|
+
})),
|
|
1049
|
+
cleanup_residual_count: Number.isInteger(row?.cleanup_residual_count)
|
|
1050
|
+
? row.cleanup_residual_count
|
|
1051
|
+
: null,
|
|
1052
|
+
security_privacy_check_count: Array.isArray(row?.security_privacy_checks)
|
|
1053
|
+
? row.security_privacy_checks.length
|
|
1054
|
+
: 0,
|
|
1055
|
+
browser_artifact_count: Array.isArray(row?.browser_artifacts)
|
|
1056
|
+
? row.browser_artifacts.length
|
|
1057
|
+
: 0,
|
|
1058
|
+
locale_count: Array.isArray(row?.locales_checked) ? row.locales_checked.length : 0,
|
|
1059
|
+
console_error_count: Number.isInteger(row?.console_error_count)
|
|
1060
|
+
? row.console_error_count
|
|
1061
|
+
: null,
|
|
1062
|
+
network_failure_count: Number.isInteger(row?.network_failure_count)
|
|
1063
|
+
? row.network_failure_count
|
|
1064
|
+
: null,
|
|
1065
|
+
heading_levels_checked: (Array.isArray(row?.heading_levels_checked)
|
|
1066
|
+
? row.heading_levels_checked
|
|
1067
|
+
: []).filter((item) => Number.isInteger(item) && item >= 1 && item <= 6),
|
|
1068
|
+
leading_space_checked: row?.leading_space_checked === true,
|
|
1069
|
+
trailing_hash_checked: row?.trailing_hash_checked === true,
|
|
1070
|
+
single_official_checklist: row?.single_official_checklist === true,
|
|
1071
|
+
unverified_model_output_labeled: row?.unverified_model_output_labeled === true,
|
|
1072
|
+
deployment_target_present: Boolean(row?.deployment_target),
|
|
1073
|
+
deployment_target_source_present: Boolean(row?.deployment_target_source),
|
|
1074
|
+
revision_observation_method_present: Boolean(row?.revision_observation_method),
|
|
1075
|
+
live_write_policy: ["no_persistence", "scoped_fixture", "authorized_production_write"]
|
|
1076
|
+
.includes(row?.live_write_policy) ? row.live_write_policy : null,
|
|
1077
|
+
resume_paths_checked: (Array.isArray(row?.resume_paths_checked)
|
|
1078
|
+
? row.resume_paths_checked
|
|
1079
|
+
: []).filter((item) => ["normal", "paid", "checkpoint"].includes(item)),
|
|
1080
|
+
paid_resume_support: ["supported", "not_supported"].includes(row?.paid_resume_support)
|
|
1081
|
+
? row.paid_resume_support
|
|
1082
|
+
: null,
|
|
1083
|
+
paid_resume_support_source_present: Boolean(row?.paid_resume_support_source),
|
|
1084
|
+
derived_views_recomputed: row?.derived_views_recomputed === true,
|
|
1085
|
+
artifact_content_preserved: row?.artifact_content_preserved === true,
|
|
1086
|
+
}));
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
function skippedChecksForLedger(value) {
|
|
1090
|
+
return (Array.isArray(value) ? value : []).map((row) => ({
|
|
1091
|
+
name_present: Boolean(row?.name),
|
|
1092
|
+
reason_present: Boolean(row?.reason),
|
|
1093
|
+
impact_present: Boolean(row?.impact),
|
|
1094
|
+
}));
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
function validatedHashesForLedger(value, length) {
|
|
1098
|
+
return stringArrayForLedger(value)
|
|
1099
|
+
.map((item) => validatedHashForLedger(item, length))
|
|
1100
|
+
.filter(Boolean);
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
function validatedHashForLedger(value, length) {
|
|
1104
|
+
const candidate = typeof value === "string" ? value.trim().toLowerCase() : "";
|
|
1105
|
+
return new RegExp(`^[a-f0-9]{${length}}$`).test(candidate) ? candidate : null;
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1013
1108
|
function redactedEventDetail(value, lifecycleState, attachments) {
|
|
1014
1109
|
const detail = value && typeof value === "object" ? value : {};
|
|
1015
1110
|
const result = {};
|
|
@@ -1070,7 +1165,7 @@ function observedEvidenceForLedger(value) {
|
|
|
1070
1165
|
head_branch: github.head_branch || null,
|
|
1071
1166
|
head_sha: github.head_sha || null,
|
|
1072
1167
|
base_branch: github.base_branch || null,
|
|
1073
|
-
checks:
|
|
1168
|
+
checks: githubChecksForLedger(github.checks),
|
|
1074
1169
|
checks_present: github.checks_present === true,
|
|
1075
1170
|
checks_passing: github.checks_passing === true,
|
|
1076
1171
|
required_checks_present: github.required_checks_present === true,
|
|
@@ -1082,6 +1177,14 @@ function stringArrayForLedger(value) {
|
|
|
1082
1177
|
return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
|
|
1083
1178
|
}
|
|
1084
1179
|
|
|
1180
|
+
function githubChecksForLedger(value) {
|
|
1181
|
+
const allowedStates = new Set(["success", "skipped", "failure", "pending"]);
|
|
1182
|
+
return (Array.isArray(value) ? value : []).map((item) => ({
|
|
1183
|
+
name_present: Boolean(item?.name),
|
|
1184
|
+
state: allowedStates.has(item?.state) ? item.state : "pending",
|
|
1185
|
+
}));
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1085
1188
|
export function toCompatibleCodingLoopState(state) {
|
|
1086
1189
|
switch (state) {
|
|
1087
1190
|
case "risk_classifying":
|
package/src/sqm/agent-skill.js
CHANGED
|
@@ -104,8 +104,12 @@ export async function installSqmAgentSkill({ home = homedir(), platforms = Objec
|
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
export async function inspectCodexPlugin({ home = homedir() } = {}) {
|
|
107
|
-
const
|
|
108
|
-
const
|
|
107
|
+
const overrides = await installedPluginOverrides();
|
|
108
|
+
const manifest = await bundledPluginManifest({ overrides });
|
|
109
|
+
const expectedDigest = await directoryDigest(BUNDLED_CODEX_PLUGIN_ROOT, {
|
|
110
|
+
manifest,
|
|
111
|
+
overrides,
|
|
112
|
+
});
|
|
109
113
|
const target = codexPluginPath(home);
|
|
110
114
|
const installedDigest = await directoryDigest(target, { missing: null });
|
|
111
115
|
const marketplacePath = codexMarketplacePath(home);
|
|
@@ -152,8 +156,12 @@ async function installCodexPlugin({ home }) {
|
|
|
152
156
|
await rm(staged, { recursive: true, force: true });
|
|
153
157
|
await rm(backup, { recursive: true, force: true });
|
|
154
158
|
await cp(BUNDLED_CODEX_PLUGIN_ROOT, staged, { recursive: true, errorOnExist: true });
|
|
159
|
+
const overrides = await installedPluginOverrides();
|
|
160
|
+
for (const [relative, content] of overrides) {
|
|
161
|
+
await writeFile(path.join(staged, relative), content);
|
|
162
|
+
}
|
|
155
163
|
await writeFile(path.join(staged, ".codex-plugin", "plugin.json"),
|
|
156
|
-
`${JSON.stringify(await bundledPluginManifest(), null, 2)}\n`);
|
|
164
|
+
`${JSON.stringify(await bundledPluginManifest({ overrides }), null, 2)}\n`);
|
|
157
165
|
let backedUp = false;
|
|
158
166
|
try {
|
|
159
167
|
if (await pathExists(target)) {
|
|
@@ -303,14 +311,36 @@ async function fileDigest(target) {
|
|
|
303
311
|
}
|
|
304
312
|
}
|
|
305
313
|
|
|
306
|
-
async function bundledPluginManifest() {
|
|
314
|
+
async function bundledPluginManifest({ overrides = new Map() } = {}) {
|
|
307
315
|
const manifest = JSON.parse(await readFile(path.join(BUNDLED_CODEX_PLUGIN_ROOT, ".codex-plugin", "plugin.json"), "utf8"));
|
|
308
316
|
// A stable content-derived version refreshes Codex's cache only when the bundle changes.
|
|
309
|
-
const digest = await directoryDigest(BUNDLED_CODEX_PLUGIN_ROOT);
|
|
317
|
+
const digest = await directoryDigest(BUNDLED_CODEX_PLUGIN_ROOT, { overrides });
|
|
310
318
|
return { ...manifest, version: `${manifest.version.split("+")[0]}+codex.${digest}` };
|
|
311
319
|
}
|
|
312
320
|
|
|
313
|
-
async function
|
|
321
|
+
async function installedPluginOverrides() {
|
|
322
|
+
const relative = "hooks/hooks.json";
|
|
323
|
+
const source = JSON.parse(await readFile(path.join(BUNDLED_CODEX_PLUGIN_ROOT, relative), "utf8"));
|
|
324
|
+
const commandPrefix = "node ";
|
|
325
|
+
const runtime = shellQuote(process.execPath);
|
|
326
|
+
for (const groups of Object.values(source.hooks || {})) {
|
|
327
|
+
for (const group of groups || []) {
|
|
328
|
+
for (const hook of group.hooks || []) {
|
|
329
|
+
if (typeof hook.command === "string" && hook.command.startsWith(commandPrefix)) {
|
|
330
|
+
hook.command = `${runtime} ${hook.command.slice(commandPrefix.length)}`;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
return new Map([[relative, `${JSON.stringify(source, null, 2)}\n`]]);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
function shellQuote(value) {
|
|
339
|
+
if (process.platform === "win32") return `"${value.replaceAll('"', '""')}"`;
|
|
340
|
+
return `'${value.replaceAll("'", "'\\''")}'`;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
async function directoryDigest(root, { missing = "throw", manifest, overrides = new Map() } = {}) {
|
|
314
344
|
let rootStat;
|
|
315
345
|
try {
|
|
316
346
|
rootStat = await lstat(root);
|
|
@@ -336,7 +366,9 @@ async function directoryDigest(root, { missing = "throw", manifest } = {}) {
|
|
|
336
366
|
if (!entry.isFile()) throw new Error(`${target} must be a regular file.`);
|
|
337
367
|
const content = manifest && relative === ".codex-plugin/plugin.json"
|
|
338
368
|
? `${JSON.stringify(manifest, null, 2)}\n`
|
|
339
|
-
:
|
|
369
|
+
: overrides.has(relative)
|
|
370
|
+
? overrides.get(relative)
|
|
371
|
+
: await readFile(target);
|
|
340
372
|
hash.update(relative).update("\0").update(content).update("\0");
|
|
341
373
|
}
|
|
342
374
|
};
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|