okstra 0.170.3 → 0.172.0
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/docs/architecture.md +13 -0
- package/docs/cli.md +4 -2
- package/docs/for-ai/skills/okstra-user-response.md +2 -2
- package/docs/project-structure-overview.md +3 -1
- package/package.json +1 -1
- package/runtime/BUILD.json +2 -2
- package/runtime/prompts/launch.template.md +4 -0
- package/runtime/prompts/lead/adapters/cmux.md +1 -1
- package/runtime/prompts/lead/okstra-lead-contract.md +36 -12
- package/runtime/prompts/lead/plan-body-verification.md +22 -11
- package/runtime/prompts/lead/report-writer.md +11 -10
- package/runtime/prompts/lead/team-contract.md +2 -0
- package/runtime/prompts/profiles/_clarification-recommendation.md +3 -1
- package/runtime/prompts/profiles/_common-contract.md +2 -1
- package/runtime/prompts/profiles/implementation-planning.md +8 -1
- package/runtime/python/okstra_ctl/adapters/hosts/antigravity/relay.md +1 -1
- package/runtime/python/okstra_ctl/adapters/hosts/claude-code/relay.md +1 -1
- package/runtime/python/okstra_ctl/adapters/hosts/codex/relay.md +1 -1
- package/runtime/python/okstra_ctl/adapters/hosts/external/relay.md +1 -1
- package/runtime/python/okstra_ctl/adapters/hosts/grok/relay.md +1 -1
- package/runtime/python/okstra_ctl/adapters/hosts/kimi/relay.md +1 -1
- package/runtime/python/okstra_ctl/agent_activity.py +306 -0
- package/runtime/python/okstra_ctl/clarification_items.py +37 -20
- package/runtime/python/okstra_ctl/cmux.py +144 -59
- package/runtime/python/okstra_ctl/lead_events.py +47 -4
- package/runtime/python/okstra_ctl/render.py +11 -3
- package/runtime/python/okstra_ctl/report_finalize.py +51 -14
- package/runtime/python/okstra_ctl/report_html/common.py +5 -3
- package/runtime/python/okstra_ctl/report_html/view_models/implementation_planning.py +17 -1
- package/runtime/python/okstra_ctl/report_translation.py +14 -0
- package/runtime/python/okstra_ctl/worker_audit_ledger.py +150 -0
- package/runtime/schemas/final-report-v2.0.schema.json +189 -0
- package/runtime/skills/okstra-user-response/SKILL.md +2 -2
- package/runtime/templates/reports/final-report-v2.template.md +8 -0
- package/runtime/templates/reports/html/assets/base.css +7 -0
- package/runtime/templates/reports/html/i18n/en.json +6 -1
- package/runtime/templates/reports/html/i18n/ko.json +6 -1
- package/runtime/templates/reports/html/macros/forms.html +21 -2
- package/runtime/templates/reports/html/tasks/implementation-planning.template.html +25 -0
- package/runtime/templates/reports/i18n/en.json +4 -0
- package/runtime/templates/reports/report.js +26 -17
- package/runtime/templates/reports/user-response.template.md +3 -1
- package/runtime/templates/worker-prompt-preamble.md +8 -0
- package/runtime/validators/validate-run.py +989 -29
- package/runtime/validators/validate_session_conformance.py +523 -35
- package/src/cli-registry.mjs +7 -0
- package/src/commands/report/agent-activity.mjs +21 -0
|
@@ -44,33 +44,37 @@
|
|
|
44
44
|
return String(s == null ? "" : s).replace(/^\s+|\s+$/g, "");
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
// Read the user-supplied value
|
|
48
|
-
//
|
|
49
|
-
|
|
50
|
-
// "기타" branch has an empty input. Caller decides whether to emit
|
|
51
|
-
// an entry.
|
|
52
|
-
function readRowValue(row) {
|
|
47
|
+
// Read the user-supplied value and decision effect from one clarification
|
|
48
|
+
// row. Returns null when the row has no usable input.
|
|
49
|
+
function readRowInput(row) {
|
|
53
50
|
var sel = row.querySelector("select[data-response-id]");
|
|
54
51
|
if (sel) {
|
|
55
|
-
if (sel.disabled) return
|
|
52
|
+
if (sel.disabled) return null;
|
|
56
53
|
var picked = sel.value;
|
|
57
|
-
if (picked === "") return
|
|
54
|
+
if (picked === "") return null;
|
|
58
55
|
if (picked === "__other__") {
|
|
59
56
|
var rid = sel.getAttribute("data-response-id") || "";
|
|
60
57
|
var other = row.querySelector('textarea[data-other-for="' + rid + '"]');
|
|
61
|
-
|
|
58
|
+
if (other) {
|
|
59
|
+
var otherValue = trimMultiline(other.value);
|
|
60
|
+
return otherValue ? { value: otherValue, disposition: "answer" } : null;
|
|
61
|
+
}
|
|
62
62
|
}
|
|
63
63
|
var opt = sel.options[sel.selectedIndex];
|
|
64
64
|
// Use the visible option text ("(a) one-time backfill") so the
|
|
65
65
|
// user-response sidecar stays human-readable, not just "a".
|
|
66
|
-
return
|
|
66
|
+
return {
|
|
67
|
+
value: opt ? trimMultiline(opt.textContent) : picked,
|
|
68
|
+
disposition: opt ? (opt.getAttribute("data-disposition") || "answer") : "answer",
|
|
69
|
+
};
|
|
67
70
|
}
|
|
68
71
|
var ta = row.querySelector("textarea[data-response-id]");
|
|
69
72
|
if (ta) {
|
|
70
|
-
if (ta.disabled) return
|
|
71
|
-
|
|
73
|
+
if (ta.disabled) return null;
|
|
74
|
+
var value = trimMultiline(ta.value);
|
|
75
|
+
return value ? { value: value, disposition: "answer" } : null;
|
|
72
76
|
}
|
|
73
|
-
return
|
|
77
|
+
return null;
|
|
74
78
|
}
|
|
75
79
|
|
|
76
80
|
function collectEntries() {
|
|
@@ -84,13 +88,14 @@
|
|
|
84
88
|
);
|
|
85
89
|
for (var i = 0; i < rows.length; i++) {
|
|
86
90
|
var row = rows[i];
|
|
87
|
-
var
|
|
88
|
-
if (!
|
|
91
|
+
var input = readRowInput(row);
|
|
92
|
+
if (!input) continue;
|
|
89
93
|
entries.push({
|
|
90
94
|
responseId: row.getAttribute("data-response-id") || "",
|
|
91
95
|
kind: row.getAttribute("data-kind") || "",
|
|
92
|
-
value: value,
|
|
96
|
+
value: input.value,
|
|
93
97
|
rationale: null,
|
|
98
|
+
disposition: input.disposition,
|
|
94
99
|
});
|
|
95
100
|
}
|
|
96
101
|
return entries;
|
|
@@ -460,11 +465,15 @@
|
|
|
460
465
|
// globalThis (works under ESM where the parent uses `vm.runInThisContext`
|
|
461
466
|
// — see tests/test_report_views.py for the byte-identity harness).
|
|
462
467
|
if (typeof module !== "undefined" && module.exports) {
|
|
463
|
-
module.exports = {
|
|
468
|
+
module.exports = {
|
|
469
|
+
buildUserResponseMarkdown: buildUserResponseMarkdown,
|
|
470
|
+
collectEntries: collectEntries,
|
|
471
|
+
};
|
|
464
472
|
}
|
|
465
473
|
if (typeof globalThis !== "undefined") {
|
|
466
474
|
globalThis.__okstraReportViewExports__ = {
|
|
467
475
|
buildUserResponseMarkdown: buildUserResponseMarkdown,
|
|
476
|
+
collectEntries: collectEntries,
|
|
468
477
|
};
|
|
469
478
|
}
|
|
470
479
|
})();
|
|
@@ -25,12 +25,14 @@ The schema of each response block:
|
|
|
25
25
|
```markdown
|
|
26
26
|
## <Response ID>
|
|
27
27
|
- Kind: <material | decision | data-point>
|
|
28
|
-
- Disposition: <answer | reframe> # omit the line when answer (default)
|
|
28
|
+
- Disposition: <answer | reframe | select | accept-risk | request-revision | reject> # omit the line when answer (default)
|
|
29
29
|
- Value:
|
|
30
30
|
> <multi-line value, trimmed>
|
|
31
31
|
- Rationale: <optional one-line rationale>
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
+
`answer`, `select`, `accept-risk`, `request-revision`, and `reject` count as user answers when `Value` is non-empty. `reframe` alone does not count as an answer; it defers the answer and asks the next run to present the row again.
|
|
35
|
+
|
|
34
36
|
An empty response set (when the user presses Export without filling in any row) outputs the following single line in the body:
|
|
35
37
|
|
|
36
38
|
```markdown
|
|
@@ -21,6 +21,14 @@ When `**Evidence ledger:** required-v1` is present, append one canonical row to
|
|
|
21
21
|
|
|
22
22
|
Every file citation in the result MUST use backticks, a line suffix, and the same project-relative path its ledger row carries — for example `src/config/env.ts:1-22`. A bare filename (`env.ts:1-22`) does not match its row and fails exactly like a file you never opened, however many times you cited the full path earlier. A cited path without a matching ledger row fails Phase 7 in `validators/validate-run.py` `validate_worker_results_audit()`. Do not add a row for a file you did not open.
|
|
23
23
|
|
|
24
|
+
## Evidence command ledger
|
|
25
|
+
|
|
26
|
+
Append one canonical JSON row to the audit sidecar for each command that produced or verified a conclusion:
|
|
27
|
+
|
|
28
|
+
- Evidence command: {"command":"npm run check","cwd":"<project-root>","exitCode":0,"outputSummary":"all checks passed"}
|
|
29
|
+
|
|
30
|
+
Do not record commands used only to explore, including `rg`, `ls`, and file-opening commands. Do not record environment variable values, tokens, credentials, or authorization headers. `okstra worker-audit-check` rejects malformed command rows and rows containing potential sensitive material through `okstra_ctl.worker_audit_ledger`.
|
|
31
|
+
|
|
24
32
|
## Anchor headers (lead-injected, BLOCKING)
|
|
25
33
|
|
|
26
34
|
Every initial analysis prompt begins with these generated anchors in this exact order, before any other content:
|