okstra 0.180.0 → 0.183.2
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/cli-registry.mjs +16 -2
- package/dist/cli-registry.mjs.map +1 -1
- package/dist/commands/execute/render-bundle.d.mts +4 -2
- package/dist/commands/execute/render-bundle.mjs +46 -5
- package/dist/commands/execute/render-bundle.mjs.map +1 -1
- package/dist/commands/execute/run.mjs +11 -3
- package/dist/commands/execute/run.mjs.map +1 -1
- package/dist/commands/inspect/model-io.d.mts +1 -0
- package/dist/commands/inspect/model-io.mjs +25 -0
- package/dist/commands/inspect/model-io.mjs.map +1 -0
- package/dist/commands/inspect/stage-map.mjs +29 -8
- package/dist/commands/inspect/stage-map.mjs.map +1 -1
- package/dist/commands/inspect/task-list.mjs +52 -6
- package/dist/commands/inspect/task-list.mjs.map +1 -1
- package/dist/commands/inspect/user-response.mjs +14 -4
- package/dist/commands/inspect/user-response.mjs.map +1 -1
- package/dist/commands/lifecycle/check-project.d.mts +1 -0
- package/dist/commands/lifecycle/check-project.mjs +69 -50
- package/dist/commands/lifecycle/check-project.mjs.map +1 -1
- package/dist/commands/lifecycle/contract-check.d.mts +1 -0
- package/dist/commands/lifecycle/contract-check.mjs +18 -0
- package/dist/commands/lifecycle/contract-check.mjs.map +1 -0
- package/dist/commands/lifecycle/preflight.mjs +154 -51
- package/dist/commands/lifecycle/preflight.mjs.map +1 -1
- package/dist/commands/pr/pr.d.mts +1 -0
- package/dist/commands/pr/pr.mjs +19 -1
- package/dist/commands/pr/pr.mjs.map +1 -1
- package/dist/commands/report/agent-activity.mjs +2 -2
- package/dist/commands/report/translate.mjs +3 -0
- package/dist/commands/report/translate.mjs.map +1 -1
- package/dist/lib/host-registry-client.mjs +13 -9
- package/dist/lib/host-registry-client.mjs.map +1 -1
- package/docs/architecture.md +11 -0
- package/docs/cli.md +26 -13
- package/docs/container.md +6 -4
- package/docs/contributor-change-matrix.md +1 -1
- package/docs/for-ai/README.md +2 -2
- package/docs/for-ai/skills/okstra-brief-gen.md +5 -3
- package/docs/for-ai/skills/okstra-code-review.md +4 -4
- package/docs/for-ai/skills/okstra-container-build.md +20 -17
- package/docs/for-ai/skills/okstra-inspect.md +20 -23
- package/docs/for-ai/skills/okstra-manager.md +19 -18
- package/docs/for-ai/skills/okstra-memory.md +2 -2
- package/docs/for-ai/skills/okstra-pr-gen.md +3 -3
- package/docs/for-ai/skills/okstra-rollup.md +14 -13
- package/docs/for-ai/skills/okstra-run.md +7 -3
- package/docs/for-ai/skills/okstra-schedule-gen.md +15 -18
- package/docs/for-ai/skills/okstra-setup.md +7 -7
- package/docs/for-ai/skills/okstra-usage.md +5 -4
- package/docs/for-ai/skills/okstra-user-response.md +50 -32
- package/docs/project-structure-overview.md +29 -26
- package/docs/task-process/implementation.md +7 -4
- package/package.json +1 -1
- package/runtime/BUILD.json +2 -2
- package/runtime/agents/workers/claude-worker.md +4 -4
- package/runtime/agents/workers/report-writer-worker.md +3 -3
- package/runtime/agents/workers/translator-worker.md +5 -13
- package/runtime/bin/okstra-error-log.py +51 -11
- package/runtime/bin/okstra-report-translate.py +210 -23
- package/runtime/prompts/host-orchestration/implementation.md +1 -1
- package/runtime/prompts/launch.template.md +3 -7
- package/runtime/prompts/lead/context-loader.md +41 -141
- package/runtime/prompts/lead/convergence.md +8 -6
- package/runtime/prompts/lead/okstra-lead-contract.md +25 -35
- package/runtime/prompts/lead/plan-body-verification.md +187 -14
- package/runtime/prompts/lead/report-writer.md +20 -1
- package/runtime/prompts/lead/team-contract.md +8 -53
- package/runtime/prompts/profiles/_coding-conventions-preflight.md +3 -2
- package/runtime/prompts/profiles/_common-contract.md +1 -1
- package/runtime/prompts/profiles/_implementation-diff-review.md +1 -1
- package/runtime/prompts/profiles/_implementation-verifier.md +3 -3
- package/runtime/prompts/profiles/final-verification.md +1 -1
- package/runtime/prompts/profiles/implementation-planning.md +8 -2
- package/runtime/prompts/profiles/release-handoff.md +0 -1
- package/runtime/prompts/wizard/prompts.ko.json +0 -1
- package/runtime/python/okstra_ctl/adapters/hosts/capability_adapter.py +69 -17
- package/runtime/python/okstra_ctl/adapters/hosts/claude-code/adapter.py +13 -4
- package/runtime/python/okstra_ctl/adapters/hosts/claude-code/relay.md +6 -1
- package/runtime/python/okstra_ctl/adapters/hosts/codex/adapter.py +2 -2
- package/runtime/python/okstra_ctl/adapters/hosts/codex/relay.md +50 -5
- package/runtime/python/okstra_ctl/adapters/hosts/grok/adapter.py +2 -2
- package/runtime/python/okstra_ctl/adapters/hosts/grok/relay.md +66 -5
- package/runtime/python/okstra_ctl/adapters/providers/grok/adapter.py +70 -2
- package/runtime/python/okstra_ctl/agent_activity.py +118 -35
- package/runtime/python/okstra_ctl/agent_invocation.py +19 -6
- package/runtime/python/okstra_ctl/agent_prompt_cli.py +65 -18
- package/runtime/python/okstra_ctl/analysis_inputs.py +5 -4
- package/runtime/python/okstra_ctl/analysis_packet.py +81 -1
- package/runtime/python/okstra_ctl/approval_decisions.py +3 -2
- package/runtime/python/okstra_ctl/attempt_evidence.py +2 -2
- package/runtime/python/okstra_ctl/backfill.py +13 -10
- package/runtime/python/okstra_ctl/batch.py +2 -4
- package/runtime/python/okstra_ctl/build_tools.py +6 -3
- package/runtime/python/okstra_ctl/claim_reproduction.py +101 -0
- package/runtime/python/okstra_ctl/clarification_items.py +27 -13
- package/runtime/python/okstra_ctl/cmux.py +130 -52
- package/runtime/python/okstra_ctl/code_review_target.py +34 -8
- package/runtime/python/okstra_ctl/consumers.py +5 -4
- package/runtime/python/okstra_ctl/container.py +103 -8
- package/runtime/python/okstra_ctl/context_cost.py +2 -1
- package/runtime/python/okstra_ctl/contract_graph.py +497 -0
- package/runtime/python/okstra_ctl/contract_graph_cli.py +62 -0
- package/runtime/python/okstra_ctl/convergence.py +338 -17
- package/runtime/python/okstra_ctl/convergence_engine.py +10 -18
- package/runtime/python/okstra_ctl/convergence_provenance.py +58 -8
- package/runtime/python/okstra_ctl/convergence_store.py +55 -34
- package/runtime/python/okstra_ctl/design_prep.py +7 -4
- package/runtime/python/okstra_ctl/dispatch_core.py +35 -65
- package/runtime/python/okstra_ctl/dispatch_state.py +134 -59
- package/runtime/python/okstra_ctl/doctor.py +6 -3
- package/runtime/python/okstra_ctl/domain/worker_presentation.py +70 -9
- package/runtime/python/okstra_ctl/entrypoints/hosts.py +16 -30
- package/runtime/python/okstra_ctl/error_log_write.py +35 -30
- package/runtime/python/okstra_ctl/error_report.py +26 -1
- package/runtime/python/okstra_ctl/error_zip.py +27 -5
- package/runtime/python/okstra_ctl/execution_identity.py +3 -2
- package/runtime/python/okstra_ctl/execution_manifest.py +7 -4
- package/runtime/python/okstra_ctl/final_report_schema.py +2 -2
- package/runtime/python/okstra_ctl/fix_cycles.py +2 -2
- package/runtime/python/okstra_ctl/fixed_text.py +39 -0
- package/runtime/python/okstra_ctl/git_reconcile.py +41 -9
- package/runtime/python/okstra_ctl/handoff.py +5 -4
- package/runtime/python/okstra_ctl/i18n.py +4 -2
- package/runtime/python/okstra_ctl/implementation_direction.py +22 -14
- package/runtime/python/okstra_ctl/implementation_outcome.py +4 -7
- package/runtime/python/okstra_ctl/incremental_carry.py +2 -1
- package/runtime/python/okstra_ctl/incremental_scope.py +8 -3
- package/runtime/python/okstra_ctl/index.py +8 -11
- package/runtime/python/okstra_ctl/initial_prompt_materialization.py +79 -7
- package/runtime/python/okstra_ctl/invocation.py +3 -6
- package/runtime/python/okstra_ctl/json_boundary.py +366 -0
- package/runtime/python/okstra_ctl/json_registry.py +10 -12
- package/runtime/python/okstra_ctl/jsonl.py +19 -2
- package/runtime/python/okstra_ctl/lead_events.py +33 -1
- package/runtime/python/okstra_ctl/listing.py +3 -3
- package/runtime/python/okstra_ctl/log_report.py +24 -2
- package/runtime/python/okstra_ctl/manager_cli.py +92 -7
- package/runtime/python/okstra_ctl/manager_store.py +12 -10
- package/runtime/python/okstra_ctl/material.py +5 -1
- package/runtime/python/okstra_ctl/migrate.py +29 -25
- package/runtime/python/okstra_ctl/model_cli.py +3 -15
- package/runtime/python/okstra_ctl/model_io_cli.py +1051 -0
- package/runtime/python/okstra_ctl/mutation_probe.py +13 -4
- package/runtime/python/okstra_ctl/pane_reclaim.py +3 -2
- package/runtime/python/okstra_ctl/paths.py +9 -0
- package/runtime/python/okstra_ctl/plan_items.py +115 -4
- package/runtime/python/okstra_ctl/plan_items_cli.py +513 -18
- package/runtime/python/okstra_ctl/pr_template.py +3 -2
- package/runtime/python/okstra_ctl/project_meta.py +5 -7
- package/runtime/python/okstra_ctl/recap.py +5 -4
- package/runtime/python/okstra_ctl/reconcile.py +21 -27
- package/runtime/python/okstra_ctl/registry/host_discovery.py +3 -2
- package/runtime/python/okstra_ctl/registry/provider_registry.py +3 -2
- package/runtime/python/okstra_ctl/render.py +26 -15
- package/runtime/python/okstra_ctl/render_final_report.py +3 -2
- package/runtime/python/okstra_ctl/report_assembly.py +172 -17
- package/runtime/python/okstra_ctl/report_finalize.py +7 -10
- package/runtime/python/okstra_ctl/report_html/render.py +3 -2
- package/runtime/python/okstra_ctl/report_language.py +3 -2
- package/runtime/python/okstra_ctl/report_markdown.py +13 -1
- package/runtime/python/okstra_ctl/report_narrative.py +40 -8
- package/runtime/python/okstra_ctl/report_synthesis_packet.py +518 -0
- package/runtime/python/okstra_ctl/report_views.py +3 -2
- package/runtime/python/okstra_ctl/rollup.py +65 -4
- package/runtime/python/okstra_ctl/run.py +159 -56
- package/runtime/python/okstra_ctl/run_audit.py +3 -2
- package/runtime/python/okstra_ctl/run_context.py +6 -9
- package/runtime/python/okstra_ctl/run_index_row.py +2 -8
- package/runtime/python/okstra_ctl/schedule_semantics.py +5 -2
- package/runtime/python/okstra_ctl/schema_excerpt.py +4 -2
- package/runtime/python/okstra_ctl/session_transcript.py +27 -1
- package/runtime/python/okstra_ctl/set_work_status.py +64 -38
- package/runtime/python/okstra_ctl/stage_fix_carry.py +4 -2
- package/runtime/python/okstra_ctl/stage_map.py +26 -6
- package/runtime/python/okstra_ctl/stage_targets.py +3 -4
- package/runtime/python/okstra_ctl/team.py +2 -1
- package/runtime/python/okstra_ctl/team_reconcile.py +11 -2
- package/runtime/python/okstra_ctl/time_report.py +51 -4
- package/runtime/python/okstra_ctl/usage_identity.py +2 -1
- package/runtime/python/okstra_ctl/usage_report.py +58 -4
- package/runtime/python/okstra_ctl/user_response.py +1431 -66
- package/runtime/python/okstra_ctl/wizard.py +11 -44
- package/runtime/python/okstra_ctl/work_categories.py +3 -2
- package/runtime/python/okstra_ctl/worker_prompt_body.py +18 -7
- package/runtime/python/okstra_ctl/worker_prompt_contract.py +3 -2
- package/runtime/python/okstra_ctl/worker_runner.py +14 -12
- package/runtime/python/okstra_ctl/workflow.py +2 -1
- package/runtime/python/okstra_ctl/worktree.py +3 -2
- package/runtime/python/okstra_ctl/wrapper_status.py +4 -2
- package/runtime/python/okstra_ctl/write_policy.py +4 -2
- package/runtime/python/okstra_token_usage/antigravity.py +39 -12
- package/runtime/python/okstra_token_usage/collect.py +90 -38
- package/runtime/python/okstra_token_usage/grok.py +127 -0
- package/runtime/schemas/final-report-v2.0.schema.json +9 -0
- package/runtime/schemas/final-report-v3.0.schema.json +9 -0
- package/runtime/schemas/report-synthesis-packet-v1.0.schema.json +140 -0
- package/runtime/skills/okstra-brief-gen/SKILL.md +9 -7
- package/runtime/skills/okstra-code-review/SKILL.md +21 -11
- package/runtime/skills/okstra-container-build/SKILL.md +18 -18
- package/runtime/skills/okstra-inspect/SKILL.md +12 -11
- package/runtime/skills/okstra-inspect/facets/error-zip.md +8 -8
- package/runtime/skills/okstra-inspect/facets/errors.md +2 -2
- package/runtime/skills/okstra-inspect/facets/history.md +9 -14
- package/runtime/skills/okstra-inspect/facets/logs.md +2 -2
- package/runtime/skills/okstra-inspect/facets/recap.md +5 -5
- package/runtime/skills/okstra-inspect/facets/report.md +6 -10
- package/runtime/skills/okstra-inspect/facets/status.md +9 -8
- package/runtime/skills/okstra-inspect/facets/time.md +3 -3
- package/runtime/skills/okstra-manager/SKILL.md +16 -14
- package/runtime/skills/okstra-memory/SKILL.md +3 -3
- package/runtime/skills/okstra-pr-gen/SKILL.md +5 -4
- package/runtime/skills/okstra-rollup/SKILL.md +6 -16
- package/runtime/skills/okstra-run/SKILL.md +7 -7
- package/runtime/skills/okstra-schedule-gen/SKILL.md +21 -17
- package/runtime/skills/okstra-setup/SKILL.md +21 -13
- package/runtime/skills/okstra-setup/references/project-config.md +2 -2
- package/runtime/skills/okstra-usage/SKILL.md +10 -10
- package/runtime/skills/okstra-user-response/SKILL.md +78 -107
- package/runtime/templates/report-writer-prompt-preamble.md +17 -1
- package/runtime/templates/reports/schedule.template.md +4 -4
- package/runtime/templates/worker-error-contract.md +17 -29
- package/runtime/validators/validate-run.py +379 -63
- package/runtime/validators/validate_session_conformance.py +43 -7
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"""Grok Build session collectors.
|
|
2
|
+
|
|
3
|
+
공식 세션 문서는 대화를 ``~/.grok/sessions/`` 에 둔다. cwd 는 퍼센트 인코딩된
|
|
4
|
+
디렉터리 이름이다. 누적 사용량은 ``updates.jsonl`` 의
|
|
5
|
+
``params.update.usage.modelUsage`` 마지막 스냅샷이다.
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import os
|
|
10
|
+
from datetime import datetime, timezone
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from typing import Mapping
|
|
13
|
+
from urllib.parse import quote, unquote
|
|
14
|
+
|
|
15
|
+
from .jsonl_io import iter_jsonl
|
|
16
|
+
from .paths import ts_in_window
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def grok_sessions_root(
|
|
20
|
+
home: Path | None = None,
|
|
21
|
+
env: Mapping[str, str] | None = None,
|
|
22
|
+
) -> Path:
|
|
23
|
+
environ = env if env is not None else os.environ
|
|
24
|
+
configured = str(environ.get("GROK_HOME") or "").strip()
|
|
25
|
+
base = Path(configured).expanduser() if configured else (home or Path.home()) / ".grok"
|
|
26
|
+
return base / "sessions"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _iso_from_unix(value: object) -> str | None:
|
|
30
|
+
if not isinstance(value, (int, float)) or isinstance(value, bool):
|
|
31
|
+
return None
|
|
32
|
+
return datetime.fromtimestamp(value, timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _usage_payload(record: dict) -> dict | None:
|
|
36
|
+
params = record.get("params")
|
|
37
|
+
if not isinstance(params, dict):
|
|
38
|
+
return None
|
|
39
|
+
update = params.get("update")
|
|
40
|
+
if not isinstance(update, dict):
|
|
41
|
+
return None
|
|
42
|
+
usage = update.get("usage")
|
|
43
|
+
return usage if isinstance(usage, dict) else None
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _model_snapshot(usage: dict) -> tuple[dict, str | None]:
|
|
47
|
+
models = usage.get("modelUsage")
|
|
48
|
+
if isinstance(models, dict) and len(models) == 1:
|
|
49
|
+
name, payload = next(iter(models.items()))
|
|
50
|
+
if isinstance(payload, dict):
|
|
51
|
+
return payload, name if isinstance(name, str) else None
|
|
52
|
+
return usage, None
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def grok_session_total(updates_path: Path) -> dict:
|
|
56
|
+
"""마지막 modelUsage 스냅샷. 세션 누적이라 더하지 않는다."""
|
|
57
|
+
last: dict | None = None
|
|
58
|
+
model: str | None = None
|
|
59
|
+
started: str | None = None
|
|
60
|
+
ended: str | None = None
|
|
61
|
+
for record in iter_jsonl(updates_path):
|
|
62
|
+
usage = _usage_payload(record)
|
|
63
|
+
if usage is None:
|
|
64
|
+
continue
|
|
65
|
+
iso = _iso_from_unix(record.get("timestamp"))
|
|
66
|
+
if iso and started is None:
|
|
67
|
+
started = iso
|
|
68
|
+
if iso:
|
|
69
|
+
ended = iso
|
|
70
|
+
snapshot, snapshot_model = _model_snapshot(usage)
|
|
71
|
+
last = snapshot
|
|
72
|
+
if snapshot_model:
|
|
73
|
+
model = snapshot_model
|
|
74
|
+
if last is None:
|
|
75
|
+
return {"totalTokens": 0, "available": False}
|
|
76
|
+
return {
|
|
77
|
+
"totalTokens": last.get("totalTokens", 0) or 0,
|
|
78
|
+
"inputTokens": last.get("inputTokens", 0) or 0,
|
|
79
|
+
"outputTokens": last.get("outputTokens", 0) or 0,
|
|
80
|
+
"cachedInputTokens": last.get("cachedReadTokens", 0) or 0,
|
|
81
|
+
"reasoningOutputTokens": last.get("reasoningTokens", 0) or 0,
|
|
82
|
+
"durationMs": last.get("apiDurationMs", 0) or 0,
|
|
83
|
+
"model": model,
|
|
84
|
+
"startedAt": started,
|
|
85
|
+
"endedAt": ended,
|
|
86
|
+
"available": True,
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def _session_in_window(updates_path: Path, started_at: str, ended_at: str) -> bool:
|
|
91
|
+
for record in iter_jsonl(updates_path):
|
|
92
|
+
iso = _iso_from_unix(record.get("timestamp"))
|
|
93
|
+
if iso and ts_in_window(iso, started_at, ended_at):
|
|
94
|
+
return True
|
|
95
|
+
return False
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def find_grok_sessions(
|
|
99
|
+
cwd: Path,
|
|
100
|
+
started_at: str,
|
|
101
|
+
ended_at: str,
|
|
102
|
+
*,
|
|
103
|
+
session_root: Path | None = None,
|
|
104
|
+
) -> list[Path]:
|
|
105
|
+
"""cwd 로 인코딩된 세션 중 창 안에 갱신이 있는 updates.jsonl."""
|
|
106
|
+
if not started_at or not ended_at:
|
|
107
|
+
return []
|
|
108
|
+
root = session_root or grok_sessions_root()
|
|
109
|
+
if not root.is_dir():
|
|
110
|
+
return []
|
|
111
|
+
target = str(cwd)
|
|
112
|
+
matches: list[Path] = []
|
|
113
|
+
for child in root.iterdir():
|
|
114
|
+
if not child.is_dir():
|
|
115
|
+
continue
|
|
116
|
+
decoded = unquote(child.name)
|
|
117
|
+
if decoded != target:
|
|
118
|
+
continue
|
|
119
|
+
for session in child.iterdir():
|
|
120
|
+
updates = session / "updates.jsonl"
|
|
121
|
+
if updates.is_file() and _session_in_window(updates, started_at, ended_at):
|
|
122
|
+
matches.append(updates)
|
|
123
|
+
return sorted(matches)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def grok_session_dir_name(cwd: Path) -> str:
|
|
127
|
+
return quote(str(cwd), safe="")
|
|
@@ -8943,6 +8943,7 @@
|
|
|
8943
8943
|
],
|
|
8944
8944
|
"additionalProperties": false,
|
|
8945
8945
|
"properties": {
|
|
8946
|
+
"stageRefs": {"type": "array", "minItems": 1, "uniqueItems": true, "items": {"type": "integer", "minimum": 1}},
|
|
8946
8947
|
"id": {
|
|
8947
8948
|
"type": "string",
|
|
8948
8949
|
"pattern": "^VC-\\d{3,}$"
|
|
@@ -9142,6 +9143,8 @@
|
|
|
9142
9143
|
],
|
|
9143
9144
|
"additionalProperties": false,
|
|
9144
9145
|
"properties": {
|
|
9146
|
+
"setAside": {"type": "array", "items": {"type": "object", "required": ["id", "reason"], "additionalProperties": false, "properties": {"id": {"type": "string", "minLength": 1}, "reason": {"type": "string", "enum": ["record", "observed", "deferred"]}}}},
|
|
9147
|
+
"stageLedger": {"type": "object", "additionalProperties": {"type": "string", "enum": ["done", "active", "ready", "blocked"]}},
|
|
9145
9148
|
"uniformVerifiers": {
|
|
9146
9149
|
"type": "array",
|
|
9147
9150
|
"description": "Verifiers whose every vote this round was one verdict. Advisory: a unanimous round is legitimate, but the gate reads as a three-way cross-check unless this sits beside it.",
|
|
@@ -9242,6 +9245,8 @@
|
|
|
9242
9245
|
],
|
|
9243
9246
|
"additionalProperties": false,
|
|
9244
9247
|
"properties": {
|
|
9248
|
+
"block": {"type": "string", "enum": ["execution", "record"]},
|
|
9249
|
+
"stageScope": {"type": "array", "minItems": 1, "uniqueItems": true, "items": {"type": "integer", "minimum": 1}},
|
|
9245
9250
|
"id": {
|
|
9246
9251
|
"type": "string",
|
|
9247
9252
|
"minLength": 1
|
|
@@ -9280,6 +9285,9 @@
|
|
|
9280
9285
|
],
|
|
9281
9286
|
"additionalProperties": false,
|
|
9282
9287
|
"properties": {
|
|
9288
|
+
"claimKind": {"description": "Set only on DISAGREE. `fact` claims are settled by reproduction, `judgement` by quorum.", "enum": ["fact", "judgement", null]},
|
|
9289
|
+
"reproduction": {"description": "Set only on a `fact` claim. The probe okstra runs; see okstra_ctl/claim_reproduction.py.", "type": ["object", "null"]},
|
|
9290
|
+
"reproductionResult": {"description": "Written by okstra, not by the worker.", "enum": ["reproduced", "not-reproduced", "not-runnable", null]},
|
|
9283
9291
|
"worker": {
|
|
9284
9292
|
"type": "string",
|
|
9285
9293
|
"minLength": 1
|
|
@@ -9752,6 +9760,7 @@
|
|
|
9752
9760
|
],
|
|
9753
9761
|
"additionalProperties": false,
|
|
9754
9762
|
"properties": {
|
|
9763
|
+
"stageRefs": {"type": "array", "minItems": 1, "uniqueItems": true, "items": {"type": "integer", "minimum": 1}},
|
|
9755
9764
|
"id": {
|
|
9756
9765
|
"type": "string",
|
|
9757
9766
|
"pattern": "^R-\\d{3,}$"
|
|
@@ -8938,6 +8938,7 @@
|
|
|
8938
8938
|
],
|
|
8939
8939
|
"additionalProperties": false,
|
|
8940
8940
|
"properties": {
|
|
8941
|
+
"stageRefs": {"type": "array", "minItems": 1, "uniqueItems": true, "items": {"type": "integer", "minimum": 1}},
|
|
8941
8942
|
"id": {
|
|
8942
8943
|
"type": "string",
|
|
8943
8944
|
"pattern": "^VC-\\d{3,}$"
|
|
@@ -9137,6 +9138,8 @@
|
|
|
9137
9138
|
],
|
|
9138
9139
|
"additionalProperties": false,
|
|
9139
9140
|
"properties": {
|
|
9141
|
+
"setAside": {"type": "array", "items": {"type": "object", "required": ["id", "reason"], "additionalProperties": false, "properties": {"id": {"type": "string", "minLength": 1}, "reason": {"type": "string", "enum": ["record", "observed", "deferred"]}}}},
|
|
9142
|
+
"stageLedger": {"type": "object", "additionalProperties": {"type": "string", "enum": ["done", "active", "ready", "blocked"]}},
|
|
9140
9143
|
"uniformVerifiers": {
|
|
9141
9144
|
"type": "array",
|
|
9142
9145
|
"description": "Verifiers whose every vote this round was one verdict. Advisory: a unanimous round is legitimate, but the gate reads as a three-way cross-check unless this sits beside it.",
|
|
@@ -9237,6 +9240,8 @@
|
|
|
9237
9240
|
],
|
|
9238
9241
|
"additionalProperties": false,
|
|
9239
9242
|
"properties": {
|
|
9243
|
+
"block": {"type": "string", "enum": ["execution", "record"]},
|
|
9244
|
+
"stageScope": {"type": "array", "minItems": 1, "uniqueItems": true, "items": {"type": "integer", "minimum": 1}},
|
|
9240
9245
|
"id": {
|
|
9241
9246
|
"type": "string",
|
|
9242
9247
|
"minLength": 1
|
|
@@ -9272,6 +9277,9 @@
|
|
|
9272
9277
|
],
|
|
9273
9278
|
"additionalProperties": false,
|
|
9274
9279
|
"properties": {
|
|
9280
|
+
"claimKind": {"description": "Set only on DISAGREE. `fact` claims are settled by reproduction, `judgement` by quorum.", "enum": ["fact", "judgement", null]},
|
|
9281
|
+
"reproduction": {"description": "Set only on a `fact` claim. The probe okstra runs; see okstra_ctl/claim_reproduction.py.", "type": ["object", "null"]},
|
|
9282
|
+
"reproductionResult": {"description": "Written by okstra, not by the worker.", "enum": ["reproduced", "not-reproduced", "not-runnable", null]},
|
|
9275
9283
|
"worker": {
|
|
9276
9284
|
"type": "string",
|
|
9277
9285
|
"minLength": 1
|
|
@@ -9744,6 +9752,7 @@
|
|
|
9744
9752
|
],
|
|
9745
9753
|
"additionalProperties": false,
|
|
9746
9754
|
"properties": {
|
|
9755
|
+
"stageRefs": {"type": "array", "minItems": 1, "uniqueItems": true, "items": {"type": "integer", "minimum": 1}},
|
|
9747
9756
|
"id": {
|
|
9748
9757
|
"type": "string",
|
|
9749
9758
|
"pattern": "^R-\\d{3,}$"
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://okstra.dev/schemas/report-synthesis-packet-v1.0.schema.json",
|
|
4
|
+
"title": "Okstra report synthesis packet",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"required": [
|
|
7
|
+
"schemaVersion",
|
|
8
|
+
"taskKey",
|
|
9
|
+
"taskType",
|
|
10
|
+
"authoringContract",
|
|
11
|
+
"accountingSnapshot",
|
|
12
|
+
"sources"
|
|
13
|
+
],
|
|
14
|
+
"additionalProperties": false,
|
|
15
|
+
"properties": {
|
|
16
|
+
"schemaVersion": {
|
|
17
|
+
"const": "1.0"
|
|
18
|
+
},
|
|
19
|
+
"taskKey": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"minLength": 1
|
|
22
|
+
},
|
|
23
|
+
"taskType": {
|
|
24
|
+
"type": "string",
|
|
25
|
+
"minLength": 1
|
|
26
|
+
},
|
|
27
|
+
"authoringContract": {
|
|
28
|
+
"type": "object",
|
|
29
|
+
"required": [
|
|
30
|
+
"resultPath",
|
|
31
|
+
"format",
|
|
32
|
+
"sourcePolicy",
|
|
33
|
+
"instructions",
|
|
34
|
+
"runtimeOwnedContent",
|
|
35
|
+
"validationRules"
|
|
36
|
+
],
|
|
37
|
+
"additionalProperties": false,
|
|
38
|
+
"properties": {
|
|
39
|
+
"resultPath": {
|
|
40
|
+
"type": "string",
|
|
41
|
+
"minLength": 1
|
|
42
|
+
},
|
|
43
|
+
"format": {
|
|
44
|
+
"const": "report-narrative-v3.0"
|
|
45
|
+
},
|
|
46
|
+
"sourcePolicy": {
|
|
47
|
+
"const": "read-only-synthesis-packet"
|
|
48
|
+
},
|
|
49
|
+
"instructions": {
|
|
50
|
+
"type": "array",
|
|
51
|
+
"minItems": 1,
|
|
52
|
+
"uniqueItems": true,
|
|
53
|
+
"items": {
|
|
54
|
+
"type": "string",
|
|
55
|
+
"minLength": 1
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"runtimeOwnedContent": {
|
|
59
|
+
"type": "array",
|
|
60
|
+
"minItems": 1,
|
|
61
|
+
"uniqueItems": true,
|
|
62
|
+
"items": {
|
|
63
|
+
"type": "string",
|
|
64
|
+
"minLength": 1
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
"validationRules": {
|
|
68
|
+
"type": "array",
|
|
69
|
+
"minItems": 1,
|
|
70
|
+
"uniqueItems": true,
|
|
71
|
+
"items": {
|
|
72
|
+
"type": "string",
|
|
73
|
+
"minLength": 1
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"accountingSnapshot": {
|
|
79
|
+
"type": "object",
|
|
80
|
+
"required": [
|
|
81
|
+
"leadSessionIds",
|
|
82
|
+
"leadUsage",
|
|
83
|
+
"workerUsage",
|
|
84
|
+
"usageSummary"
|
|
85
|
+
],
|
|
86
|
+
"additionalProperties": false,
|
|
87
|
+
"properties": {
|
|
88
|
+
"leadSessionIds": {
|
|
89
|
+
"type": "array",
|
|
90
|
+
"items": {"type": "string"}
|
|
91
|
+
},
|
|
92
|
+
"leadUsage": {"type": "object"},
|
|
93
|
+
"workerUsage": {
|
|
94
|
+
"type": "array",
|
|
95
|
+
"items": {
|
|
96
|
+
"type": "object",
|
|
97
|
+
"required": ["workerId", "role", "usage"],
|
|
98
|
+
"additionalProperties": false,
|
|
99
|
+
"properties": {
|
|
100
|
+
"workerId": {"type": "string", "minLength": 1},
|
|
101
|
+
"role": {"type": "string"},
|
|
102
|
+
"usage": {"type": "object"}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
"usageSummary": {"type": "object"}
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
"sources": {
|
|
110
|
+
"type": "array",
|
|
111
|
+
"minItems": 1,
|
|
112
|
+
"items": {
|
|
113
|
+
"type": "object",
|
|
114
|
+
"required": ["label", "owner", "path", "digest", "content"],
|
|
115
|
+
"additionalProperties": false,
|
|
116
|
+
"properties": {
|
|
117
|
+
"label": {
|
|
118
|
+
"type": "string",
|
|
119
|
+
"minLength": 1
|
|
120
|
+
},
|
|
121
|
+
"owner": {
|
|
122
|
+
"type": "string",
|
|
123
|
+
"minLength": 1
|
|
124
|
+
},
|
|
125
|
+
"path": {
|
|
126
|
+
"type": "string",
|
|
127
|
+
"minLength": 1
|
|
128
|
+
},
|
|
129
|
+
"digest": {
|
|
130
|
+
"type": "string",
|
|
131
|
+
"pattern": "^sha256:[0-9a-f]{64}$"
|
|
132
|
+
},
|
|
133
|
+
"content": {
|
|
134
|
+
"type": "string"
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
@@ -120,10 +120,10 @@ Run one Bash tool call, starting with the literal token `okstra` (never wrapped
|
|
|
120
120
|
<!-- END FRAGMENT: bash-invocation-rule -->
|
|
121
121
|
|
|
122
122
|
```bash
|
|
123
|
-
okstra preflight --runtime claude-code
|
|
123
|
+
okstra preflight --runtime claude-code
|
|
124
124
|
```
|
|
125
125
|
|
|
126
|
-
|
|
126
|
+
On `Okstra preflight: ready`, carry the fixed `Project root` line as a literal string into the steps below. On `Okstra preflight: failed` (or `okstra` not on `PATH` at all), show the fixed `Reason` and `Recovery` lines, then stop.
|
|
127
127
|
|
|
128
128
|
<!-- BEGIN FRAGMENT: preflight-outdated-cli -->
|
|
129
129
|
If the call fails with `unknown command: preflight`, the `okstra` binary on PATH predates this skill — tell the user to update it (`npm i -g okstra@latest`), then stop (`/okstra-setup` does not update the binary).
|
|
@@ -328,16 +328,18 @@ command is its own Bash call starting with the literal token `okstra`, per
|
|
|
328
328
|
Step 0):
|
|
329
329
|
|
|
330
330
|
```bash
|
|
331
|
-
okstra task-list
|
|
331
|
+
okstra task-list --text
|
|
332
332
|
```
|
|
333
333
|
|
|
334
|
-
|
|
335
|
-
name, not a slug** — `slugify` each value (lowercase +
|
|
336
|
-
`-`) and **dedupe by slug** so case/format variants collapse (e.g.
|
|
334
|
+
Read each fixed `Task group` and `Updated at` line. `Task group` is a **raw
|
|
335
|
+
display name, not a slug** — `slugify` each value (lowercase +
|
|
336
|
+
non-alphanumeric → `-`) and **dedupe by slug** so case/format variants collapse (e.g.
|
|
337
337
|
`uploadFont` and `uploadfont` are one group, not two). Order distinct slugs
|
|
338
338
|
by most-recent `updatedAt` and take the **2 most-recent** as recommendations,
|
|
339
339
|
shown in slug form.
|
|
340
340
|
|
|
341
|
+
If `Status` is `error`, report `Failure stage` and `Failure reason`, then stop.
|
|
342
|
+
|
|
341
343
|
`AskUserQuestion` (single-select):
|
|
342
344
|
|
|
343
345
|
- **Label**: `"Task group?"`
|
|
@@ -349,7 +351,7 @@ shown in slug form.
|
|
|
349
351
|
When the user picks an existing group, use its value verbatim. When they
|
|
350
352
|
pick `Enter directly`, take a free-text value via a follow-up question.
|
|
351
353
|
|
|
352
|
-
If `okstra task-list` returns
|
|
354
|
+
If `okstra task-list --text` returns `Task count: 0` (no prior tasks), skip the
|
|
353
355
|
picker and ask one free-text question:
|
|
354
356
|
`"Task group (e.g. backend-api, INV-1234, refactor)"` → `task_group`.
|
|
355
357
|
|
|
@@ -38,12 +38,12 @@ Run one Bash tool call, starting with the literal token `okstra` (never wrapped
|
|
|
38
38
|
<!-- END FRAGMENT: bash-invocation-rule -->
|
|
39
39
|
|
|
40
40
|
```bash
|
|
41
|
-
okstra preflight --runtime claude-code
|
|
41
|
+
okstra preflight --runtime claude-code
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
Branch on the
|
|
45
|
-
- `
|
|
46
|
-
- `
|
|
44
|
+
Branch on the fixed first line:
|
|
45
|
+
- `Okstra preflight: ready` → carry `Project root` as a literal string; every later step is anchored on it.
|
|
46
|
+
- `Okstra preflight: failed` → the check only sees the cwd of the Bash call, so a project that is not the cwd can read as missing setup. Ask whether the user pointed at a specific project directory; if they did, re-run targeting it: `okstra preflight --runtime claude-code --cwd <that-dir>` (`--cwd` is the sanctioned way to target a project — a leading `cd` would break the permission match). Only if this also fails do you show `Reason` and `Recovery`, then stop.
|
|
47
47
|
|
|
48
48
|
<!-- BEGIN FRAGMENT: preflight-outdated-cli -->
|
|
49
49
|
If the call fails with `unknown command: preflight`, the `okstra` binary on PATH predates this skill — tell the user to update it (`npm i -g okstra@latest`), then stop (`/okstra-setup` does not update the binary).
|
|
@@ -63,8 +63,8 @@ Pick the mode from what the user actually gave you:
|
|
|
63
63
|
|
|
64
64
|
**Stage mode.**
|
|
65
65
|
|
|
66
|
-
1. `
|
|
67
|
-
2. `okstra stage-map <taskKey> --project <projectRoot> --
|
|
66
|
+
1. A full `project-id:task-group:task-id` token is already the task key. For a bare token, run `okstra model-io task-selection-input --project-root <projectRoot> --task-ref <token>` and branch on the fixed `Match count`, `Task`, and `Updated at` rows: **0** → report the task cannot be found and stop; **1** → take `Task`; **N** → list the candidates and ask via a 3-option picker (1–2 recommendations + `Enter directly`).
|
|
67
|
+
2. `okstra stage-map <taskKey> --project <projectRoot> --text` → use the fixed `Stages` and `Done stages` count/name/value rows.
|
|
68
68
|
3. Choose the stage with a 3-option picker — recommend the highest done stage (the work that just finished) first, a second plausible stage if there is one, and `Enter directly` last. Pick silently only when exactly one stage exists.
|
|
69
69
|
|
|
70
70
|
**Branch mode.**
|
|
@@ -75,13 +75,23 @@ Pick the mode from what the user actually gave you:
|
|
|
75
75
|
**Then call the target CLI.** One call resolves everything the rest of this skill needs; the only reason to call it again is a base the user overrides in the confirmation step below.
|
|
76
76
|
|
|
77
77
|
```bash
|
|
78
|
-
okstra code-review target --task-key <taskKey> --stage <N> --project-root <projectRoot> --
|
|
79
|
-
okstra code-review target --branch <name> [--base <ref>] --project-root <projectRoot> --
|
|
78
|
+
okstra code-review target --task-key <taskKey> --stage <N> --project-root <projectRoot> --text
|
|
79
|
+
okstra code-review target --branch <name> [--base <ref>] --project-root <projectRoot> --text
|
|
80
80
|
```
|
|
81
81
|
|
|
82
|
-
`
|
|
82
|
+
`Status: ready` carries `Project root`, `Mode`, `Worktree path`, `Branch`, `Base commit`, `Head commit`, `Review path`, and `Round`; stage mode adds `Task key`, `Task root`, and `Stage`. Carry every field verbatim into the later steps — none of them is recomputed anywhere below.
|
|
83
83
|
|
|
84
|
-
`
|
|
84
|
+
`Status: error` carries `Failure stage` and `Failure reason`. Report both and stop, unless the Exceptions table names that case.
|
|
85
|
+
|
|
86
|
+
After the range is resolved, render the only project identity and range values
|
|
87
|
+
that later model prompts may consume:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
okstra model-io code-review-input --project-root <projectRoot> --base <baseCommit> --head <headCommit>
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Carry this fixed Markdown view into the census and reviewer prompts. Do not
|
|
94
|
+
pass task manifests, target-CLI JSON, or arbitrary JSON fields to a reviewer.
|
|
85
95
|
|
|
86
96
|
**You never derive the base.** Pass `--base <ref>` only when the user named one; otherwise the CLI resolves it. `baseCommit` is a **ref, not necessarily a commit id** — a caller-supplied `--base` passes through verbatim — so use it as given in `git diff <baseCommit>..<headCommit>` and never present it as "commit `<sha>`".
|
|
87
97
|
|
|
@@ -181,7 +191,7 @@ generatedAt: <YYYY-MM-DD HH:MM>
|
|
|
181
191
|
|
|
182
192
|
| Situation | Handling |
|
|
183
193
|
|---|---|
|
|
184
|
-
| `preflight`
|
|
194
|
+
| `preflight` reports `Okstra preflight: failed` | retry with `--cwd <dir>`; if that also fails, tell the user to run `/okstra-setup` first and stop |
|
|
185
195
|
| `unknown command: code-review` | the `okstra` binary predates this skill — tell the user to update it (`npm i -g okstra@latest`) and stop |
|
|
186
196
|
| `worktreePath` is empty | not a hard stop and not a missing stage: run git in `projectRoot` against the stage's `branch` ref and continue |
|
|
187
197
|
| `baseCommit` is not an ancestor of `headCommit` — `git -C <workdir> rev-list --count <headCommit>..<baseCommit>` returns a **non-zero** count, meaning a rebase or squash rewrote the history the stage was recorded against, and `<baseCommit>..<headCommit>` would drag predecessor work in backwards | code-review is read-only, so do not force a reconcile. Offer two options: review against the branch's current tip, or run `okstra git-reconcile` first and retry |
|
|
@@ -25,10 +25,10 @@ Run one Bash tool call, starting with the literal token `okstra` (never wrapped
|
|
|
25
25
|
<!-- END FRAGMENT: bash-invocation-rule -->
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
|
-
okstra preflight --runtime claude-code
|
|
28
|
+
okstra preflight --runtime claude-code
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
On `Okstra preflight: ready`, carry the fixed `Project root` line and pass it as `--project-root <projectRoot>` to every `okstra container` call below. On `Okstra preflight: failed`, show `Reason` and `Recovery`, then stop.
|
|
32
32
|
|
|
33
33
|
<!-- BEGIN FRAGMENT: preflight-outdated-cli -->
|
|
34
34
|
If the call fails with `unknown command: preflight`, the `okstra` binary on PATH predates this skill — tell the user to update it (`npm i -g okstra@latest`), then stop (`/okstra-setup` does not update the binary).
|
|
@@ -61,7 +61,7 @@ When the user chains multiple facets in one message (e.g. "bring it up, then sho
|
|
|
61
61
|
Every sub-command needs a **task-key** (`<project-id>:<task-group>:<task-id>`) — the container group is bound to one implementation task's worktree. Resolve it the same way across sub-commands:
|
|
62
62
|
|
|
63
63
|
1. If the user gave a full task-key, use it.
|
|
64
|
-
2. If the user gave only a task-id,
|
|
64
|
+
2. If the user gave only a task-id, run `okstra model-io task-selection-input --project-root <projectRoot> --task-ref <task-id>`. Use the fixed `Selection status`, `Task key`, and numbered `Candidate` lines: one match → use its task key; multiple → list candidates and ask (3-option picker); none → report not found.
|
|
65
65
|
3. `down --all` is the only call that does not need a task-key (see `down`).
|
|
66
66
|
|
|
67
67
|
---
|
|
@@ -78,12 +78,12 @@ Brings up the task's container group: integrates the implementation stages into
|
|
|
78
78
|
Run:
|
|
79
79
|
|
|
80
80
|
```bash
|
|
81
|
-
okstra container up --project-root <projectRoot> --task-key <task-key>
|
|
81
|
+
okstra container up --project-root <projectRoot> --task-key <task-key> --text
|
|
82
82
|
```
|
|
83
83
|
|
|
84
|
-
|
|
84
|
+
Read the fixed output fields and report the provisioned services and watcher pane. If a service failed its healthcheck, the call surfaces the failing services and the `docker compose ... logs` line to inspect — relay that line; do not invent your own.
|
|
85
85
|
|
|
86
|
-
After a successful `up`, tell the user how to reach the running build
|
|
86
|
+
After a successful `up`, run the `status --text` command below and read its numbered container `ports` fields to tell the user how to reach the running build. Also explain that `okstra container status <task-key>` / `okstra container down <task-key>` manage it from here. For *what to verify* once it is up, point the user to the implementation report's §5.7.9 Manual User Test (Draft) — its steps and expected results are the manual test script for this build.
|
|
87
87
|
|
|
88
88
|
---
|
|
89
89
|
|
|
@@ -92,10 +92,10 @@ After a successful `up`, tell the user how to reach the running build (the compo
|
|
|
92
92
|
Reports the running containers (queried by run-trace label — the source of truth for "is it up") plus the watcher metadata recorded in the registry.
|
|
93
93
|
|
|
94
94
|
```bash
|
|
95
|
-
okstra container status --project-root <projectRoot> --task-key <task-key>
|
|
95
|
+
okstra container status --project-root <projectRoot> --task-key <task-key> --text
|
|
96
96
|
```
|
|
97
97
|
|
|
98
|
-
|
|
98
|
+
Read the fixed `Project name`, `Containers`, and `Watchers` fields and report:
|
|
99
99
|
|
|
100
100
|
| Field | Meaning |
|
|
101
101
|
|---|---|
|
|
@@ -112,16 +112,16 @@ If `containers` is empty, say the group is not running and offer `up`. Treat the
|
|
|
112
112
|
The live log stream lives in the tmux watcher pane, not in a file. This sub-command points at the watcher findings directory and the per-service watcher state.
|
|
113
113
|
|
|
114
114
|
```bash
|
|
115
|
-
okstra container logs --project-root <projectRoot> --task-key <task-key>
|
|
115
|
+
okstra container logs --project-root <projectRoot> --task-key <task-key> --text
|
|
116
116
|
```
|
|
117
117
|
|
|
118
118
|
Add `--service <name>` to scope to one service:
|
|
119
119
|
|
|
120
120
|
```bash
|
|
121
|
-
okstra container logs --project-root <projectRoot> --task-key <task-key> --service <service>
|
|
121
|
+
okstra container logs --project-root <projectRoot> --task-key <task-key> --service <service> --text
|
|
122
122
|
```
|
|
123
123
|
|
|
124
|
-
|
|
124
|
+
Read the fixed `Watchers dir` and numbered `Watchers` fields. Report the host path and watcher entries. Explain that the live stream is in the attached tmux pane; to see raw container logs the user runs `docker compose -p <projectName> logs -f <service>` (get `<projectName>` from `status`).
|
|
125
125
|
|
|
126
126
|
---
|
|
127
127
|
|
|
@@ -130,10 +130,10 @@ Parse the stdout JSON (`{watchersDir, watchers}`). Report the `watchersDir` host
|
|
|
130
130
|
Reaps the watcher/tail tmux panes for the task **without stopping the containers**. Use when the user wants to silence the monitor but keep the build running.
|
|
131
131
|
|
|
132
132
|
```bash
|
|
133
|
-
okstra container stop-watcher --project-root <projectRoot> --task-key <task-key>
|
|
133
|
+
okstra container stop-watcher --project-root <projectRoot> --task-key <task-key> --text
|
|
134
134
|
```
|
|
135
135
|
|
|
136
|
-
|
|
136
|
+
Read the fixed `Reaped panes` and `Note` fields. Confirm which panes were reaped and that the containers are still running. If the user actually wants the containers gone, route to `down`.
|
|
137
137
|
|
|
138
138
|
---
|
|
139
139
|
|
|
@@ -144,23 +144,23 @@ Tears down the container group (removes containers found by the run-trace label)
|
|
|
144
144
|
Single task:
|
|
145
145
|
|
|
146
146
|
```bash
|
|
147
|
-
okstra container down --project-root <projectRoot> --task-key <task-key>
|
|
147
|
+
okstra container down --project-root <projectRoot> --task-key <task-key> --text
|
|
148
148
|
```
|
|
149
149
|
|
|
150
150
|
Every container group in the project (no task-key needed):
|
|
151
151
|
|
|
152
152
|
```bash
|
|
153
|
-
okstra container down --project-root <projectRoot> --all
|
|
153
|
+
okstra container down --project-root <projectRoot> --all --text
|
|
154
154
|
```
|
|
155
155
|
|
|
156
|
-
|
|
156
|
+
Read the fixed `Downed` and `Orphan panes reaped` fields. Report each torn-down project name and the orphan panes reaped. `down` runs `docker compose -p <name> down --remove-orphans` — a compose-native teardown that removes the project's containers and the compose network, but deliberately keeps named volumes (e.g. DB data) by NOT passing `-v`. Confirm with the user before running `--all`, since it takes down every okstra container group in the project at once. A single-task `down` is safe to run directly once the task-key is resolved.
|
|
157
157
|
|
|
158
158
|
---
|
|
159
159
|
|
|
160
160
|
## Output Rules (shared)
|
|
161
161
|
|
|
162
162
|
- Responses should be concise and written in Korean unless the user requests otherwise.
|
|
163
|
-
- The
|
|
163
|
+
- The fixed text fields from each `okstra container` call are the source of truth — do not run raw `docker` commands to second-guess them unless the CLI fails and the user explicitly asks for a manual fallback.
|
|
164
164
|
- Show the resolved `<task-key>` in the heading so the user can confirm disambiguation.
|
|
165
165
|
- Surface failure messages from the CLI verbatim (compose-up failures, missing worktree/compose file) — do not paraphrase the remediation line.
|
|
166
|
-
- Display container/service states as-is from the
|
|
166
|
+
- Display container/service states as-is from the fixed fields; do not normalize or remap.
|
|
@@ -28,14 +28,14 @@ Run one Bash tool call, starting with the literal token `okstra` (never wrapped
|
|
|
28
28
|
<!-- END FRAGMENT: bash-invocation-rule -->
|
|
29
29
|
|
|
30
30
|
```bash
|
|
31
|
-
okstra preflight --runtime claude-code
|
|
31
|
+
okstra preflight --runtime claude-code
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
The project check only sees the cwd of the Bash call. When the user is asking about a project that is **not** the cwd (a sibling repo, a monorepo subdir, or a project named explicitly in the request), the bare form
|
|
34
|
+
The project check only sees the cwd of the Bash call. When the user is asking about a project that is **not** the cwd (a sibling repo, a monorepo subdir, or a project named explicitly in the request), the bare form can report `Okstra preflight: failed` — a false negative, not a missing setup; do not hard-stop on it.
|
|
35
35
|
|
|
36
|
-
Branch on the
|
|
37
|
-
- `
|
|
38
|
-
- `
|
|
36
|
+
Branch on the fixed first line:
|
|
37
|
+
- `Okstra preflight: ready` → carry `Project root` as a literal string; it is the base for every sub-command step below.
|
|
38
|
+
- `Okstra preflight: failed` → before concluding "no setup", ask whether the user pointed at a specific project directory. If they did, re-run targeting it: `okstra preflight --runtime claude-code --cwd <that-dir>` (`--cwd` is the sanctioned way to target a project — a leading `cd` would break the permission match). Only if this also fails do you show `Reason` and `Recovery`, then stop.
|
|
39
39
|
|
|
40
40
|
<!-- BEGIN FRAGMENT: preflight-outdated-cli -->
|
|
41
41
|
If the call fails with `unknown command: preflight`, the `okstra` binary on PATH predates this skill — tell the user to update it (`npm i -g okstra@latest`), then stop (`/okstra-setup` does not update the binary).
|
|
@@ -59,13 +59,14 @@ When the user chains multiple facets in one message (e.g. "status, and then time
|
|
|
59
59
|
|
|
60
60
|
### Standard task-key resolution (0/1/N)
|
|
61
61
|
|
|
62
|
-
Facets that accept a bare token (a task-id like `DEV-9184` **or** a task-group like `PROD`) resolve it
|
|
62
|
+
Facets that accept a bare token (a task-id like `DEV-9184` **or** a task-group like `PROD`) resolve it through the fixed text projection:
|
|
63
63
|
|
|
64
64
|
```bash
|
|
65
|
-
okstra
|
|
65
|
+
okstra model-io task-selection-input --project-root <projectRoot> --task-ref <token>
|
|
66
66
|
```
|
|
67
67
|
|
|
68
|
-
Branch on the
|
|
68
|
+
Branch on `Match count` in the projection and use only its repeated `Task`,
|
|
69
|
+
`Updated at`, and `Matched via` lines:
|
|
69
70
|
- **0** → report the task cannot be found. Do not guess.
|
|
70
71
|
- **1** → use that entry's `taskKey`.
|
|
71
72
|
- **N** → list the candidate `taskKey`s (with `updatedAt`, and `_matchedVia` so the user sees which came from a task-id vs a task-group) and ask via a 3-option picker (1–2 recommendations + `Enter directly`), then use the chosen `taskKey`.
|
|
@@ -74,8 +75,8 @@ Branch on the stdout JSON `matches[]`:
|
|
|
74
75
|
|
|
75
76
|
When a facet needs a task but the user did not name one:
|
|
76
77
|
|
|
77
|
-
1.
|
|
78
|
-
2.
|
|
78
|
+
1. Run `okstra model-io task-selection-input --project-root <projectRoot>`.
|
|
79
|
+
2. Branch on `Match count`; if exactly one task exists, use it.
|
|
79
80
|
3. If multiple tasks exist, show the latest 10 by `updatedAt` as real task-keys and ask which one. Do not guess, and do not answer with placeholder forms only.
|
|
80
81
|
|
|
81
82
|
## Output Rules (shared)
|
|
@@ -84,7 +85,7 @@ When a facet needs a task but the user did not name one:
|
|
|
84
85
|
status values the first time each appears — the reader has not seen the report you are summarizing.
|
|
85
86
|
- Use project-relative paths whenever possible.
|
|
86
87
|
- If there is no recent report, display `--`.
|
|
87
|
-
- If a specific task does not exist, explicitly state that
|
|
88
|
+
- If a specific task does not exist, explicitly state that the task resolver returned no match.
|
|
88
89
|
- If `awaitingApproval` is true, clearly indicate that the task is awaiting user approval.
|
|
89
90
|
- Display status fields as-is from disk (`completed`, `contract-violated`, `todo`, `error`, empty, ...). Do not normalize or remap.
|
|
90
91
|
- Dates in `YYYY-MM-DD HH:MM` format.
|