okstra 0.179.2 → 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/README.md +1 -1
- package/dist/cli-registry.mjs +30 -2
- package/dist/cli-registry.mjs.map +1 -1
- package/dist/commands/execute/incremental-carry.mjs +9 -8
- package/dist/commands/execute/incremental-carry.mjs.map +1 -1
- package/dist/commands/execute/plan-verify.mjs +3 -1
- package/dist/commands/execute/plan-verify.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/approval-decision.d.mts +1 -0
- package/dist/commands/report/approval-decision.mjs +21 -0
- package/dist/commands/report/approval-decision.mjs.map +1 -0
- package/dist/commands/report/design-snapshot.d.mts +1 -0
- package/dist/commands/report/design-snapshot.mjs +19 -0
- package/dist/commands/report/design-snapshot.mjs.map +1 -0
- 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/storage-model.md +1 -1
- package/docs/architecture.md +21 -10
- package/docs/cli.md +36 -20
- 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 +43 -31
- package/docs/task-process/implementation-planning.md +2 -2
- 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 +15 -164
- 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 +9 -12
- package/runtime/prompts/lead/adapters/cmux.md +1 -1
- package/runtime/prompts/lead/context-loader.md +41 -141
- package/runtime/prompts/lead/convergence.md +10 -8
- package/runtime/prompts/lead/okstra-lead-contract.md +40 -49
- package/runtime/prompts/lead/plan-body-verification.md +217 -23
- package/runtime/prompts/lead/report-writer.md +81 -421
- package/runtime/prompts/lead/team-contract.md +9 -54
- package/runtime/prompts/profiles/_clarification-recommendation.md +5 -4
- package/runtime/prompts/profiles/_coding-conventions-preflight.md +3 -2
- package/runtime/prompts/profiles/_common-contract.md +4 -4
- package/runtime/prompts/profiles/_implementation-deliverable.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/change-impact-analysis.md +1 -1
- package/runtime/prompts/profiles/error-analysis.md +1 -1
- package/runtime/prompts/profiles/feature-analysis.md +1 -1
- package/runtime/prompts/profiles/final-verification.md +1 -1
- package/runtime/prompts/profiles/implementation-planning.md +20 -12
- package/runtime/prompts/profiles/improvement-discovery.md +1 -1
- package/runtime/prompts/profiles/project-analysis.md +1 -1
- package/runtime/prompts/profiles/release-handoff.md +0 -1
- package/runtime/prompts/profiles/requirements-discovery.md +1 -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 +8 -2
- 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/external/relay.md +1 -1
- 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 +141 -38
- package/runtime/python/okstra_ctl/agent_invocation.py +19 -6
- package/runtime/python/okstra_ctl/agent_prompt_cli.py +70 -23
- package/runtime/python/okstra_ctl/analysis_inputs.py +5 -4
- package/runtime/python/okstra_ctl/analysis_packet.py +124 -3
- package/runtime/python/okstra_ctl/approval_decisions.py +328 -0
- 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/design_snapshot.py +134 -0
- package/runtime/python/okstra_ctl/dispatch_core.py +97 -69
- package/runtime/python/okstra_ctl/dispatch_state.py +163 -63
- 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/execution_mutation_audit.py +6 -2
- package/runtime/python/okstra_ctl/final_report_schema.py +26 -17
- 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 +130 -17
- package/runtime/python/okstra_ctl/incremental_scope.py +12 -4
- 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/path_hints.py +12 -0
- package/runtime/python/okstra_ctl/paths.py +21 -0
- package/runtime/python/okstra_ctl/plan_items.py +115 -4
- package/runtime/python/okstra_ctl/plan_items_cli.py +626 -34
- package/runtime/python/okstra_ctl/ports/worker_dispatch.py +2 -1
- 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 +74 -16
- package/runtime/python/okstra_ctl/render_final_report.py +10 -8
- package/runtime/python/okstra_ctl/report_assembly.py +509 -0
- package/runtime/python/okstra_ctl/report_contract.py +2 -1
- package/runtime/python/okstra_ctl/report_finalize.py +67 -32
- package/runtime/python/okstra_ctl/report_html/render.py +3 -2
- package/runtime/python/okstra_ctl/report_inputs.py +72 -0
- package/runtime/python/okstra_ctl/report_language.py +3 -2
- package/runtime/python/okstra_ctl/report_markdown.py +81 -8
- package/runtime/python/okstra_ctl/report_narrative.py +351 -0
- package/runtime/python/okstra_ctl/report_projections.py +265 -0
- 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 +184 -65
- 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 +15 -8
- 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 +8 -6
- package/runtime/python/okstra_ctl/stage_ledger.py +132 -18
- package/runtime/python/okstra_ctl/stage_map.py +96 -28
- package/runtime/python/okstra_ctl/stage_targets.py +3 -4
- package/runtime/python/okstra_ctl/team.py +3 -2
- 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_dispatch.py +5 -2
- package/runtime/python/okstra_ctl/worker_prompt_body.py +49 -3
- package/runtime/python/okstra_ctl/worker_prompt_contract.py +3 -2
- package/runtime/python/okstra_ctl/worker_prompt_policy.py +31 -3
- 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 +10219 -0
- package/runtime/schemas/report-narrative-v3.0.schema.json +30 -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 +29 -19
- package/runtime/templates/reports/html/macros/forms.html +6 -4
- package/runtime/templates/reports/schedule.template.md +4 -4
- package/runtime/templates/worker-error-contract.md +17 -29
- package/runtime/validators/validate-run.py +636 -72
- package/runtime/validators/validate_session_conformance.py +43 -7
|
@@ -14,16 +14,17 @@ from .claude import (
|
|
|
14
14
|
find_claude_team_sessions,
|
|
15
15
|
)
|
|
16
16
|
from .codex import codex_session_total, find_codex_sessions
|
|
17
|
-
from .antigravity import
|
|
18
|
-
|
|
19
|
-
antigravity_session_total,
|
|
20
|
-
find_antigravity_sessions,
|
|
21
|
-
)
|
|
17
|
+
from .antigravity import antigravity_session_total, find_antigravity_sessions
|
|
18
|
+
from .grok import find_grok_sessions, grok_session_total
|
|
22
19
|
from .paths import claude_project_dir, utc_now
|
|
23
20
|
from .pricing import antigravity_cost_usd, provider_cost_usd
|
|
24
21
|
from okstra_ctl.dispatch_state import worker_session_ids
|
|
25
22
|
from okstra_ctl.models import provider_wrappers
|
|
26
|
-
from okstra_ctl.wrapper_status import
|
|
23
|
+
from okstra_ctl.wrapper_status import (
|
|
24
|
+
log_path_for_prompt,
|
|
25
|
+
read_wrapper_status,
|
|
26
|
+
status_path_for_prompt,
|
|
27
|
+
)
|
|
27
28
|
|
|
28
29
|
|
|
29
30
|
def match_prefixes(worker_id: str) -> list[str]:
|
|
@@ -472,6 +473,8 @@ def _cli_sessions_for_windows(
|
|
|
472
473
|
matches = find_codex_sessions(project_root, started_at, ended_at)
|
|
473
474
|
elif provider == "antigravity":
|
|
474
475
|
matches = find_antigravity_sessions(project_root, started_at, ended_at)
|
|
476
|
+
elif provider == "grok":
|
|
477
|
+
matches = find_grok_sessions(project_root, started_at, ended_at)
|
|
475
478
|
else:
|
|
476
479
|
matches = []
|
|
477
480
|
for path in matches:
|
|
@@ -488,6 +491,8 @@ def _cli_session_totals(provider: str, session_paths: list[Path]) -> list[dict]:
|
|
|
488
491
|
total = codex_session_total(session_path)
|
|
489
492
|
elif provider == "antigravity":
|
|
490
493
|
total = antigravity_session_total(session_path)
|
|
494
|
+
elif provider == "grok":
|
|
495
|
+
total = grok_session_total(session_path)
|
|
491
496
|
else:
|
|
492
497
|
continue
|
|
493
498
|
if total.get("available"):
|
|
@@ -582,24 +587,20 @@ def collect_cli_usage(
|
|
|
582
587
|
execution = wrapper_execution(status_path)
|
|
583
588
|
execution_note = _execution_note(execution)
|
|
584
589
|
|
|
585
|
-
|
|
586
|
-
|
|
590
|
+
totals = _cli_session_totals(provider, sessions)
|
|
591
|
+
if not sessions:
|
|
592
|
+
block = na_block(
|
|
593
|
+
f"{execution_note}; CLI usage attribution unavailable because no transcript was found"
|
|
594
|
+
)
|
|
587
595
|
block["cliNote"] = block["note"]
|
|
596
|
+
elif not totals:
|
|
597
|
+
block = na_block(
|
|
598
|
+
f"{execution_note}; transcript found but no final token snapshot was recorded"
|
|
599
|
+
)
|
|
600
|
+
block["cliNote"] = block["note"]
|
|
601
|
+
block["cliSessionPaths"] = [str(path) for path in sessions]
|
|
588
602
|
else:
|
|
589
|
-
|
|
590
|
-
if not sessions:
|
|
591
|
-
block = na_block(
|
|
592
|
-
f"{execution_note}; CLI usage attribution unavailable because no transcript was found"
|
|
593
|
-
)
|
|
594
|
-
block["cliNote"] = block["note"]
|
|
595
|
-
elif not totals:
|
|
596
|
-
block = na_block(
|
|
597
|
-
f"{execution_note}; transcript found but no final token snapshot was recorded"
|
|
598
|
-
)
|
|
599
|
-
block["cliNote"] = block["note"]
|
|
600
|
-
block["cliSessionPaths"] = [str(path) for path in sessions]
|
|
601
|
-
else:
|
|
602
|
-
block = _cli_usage_block(provider, _aggregate_totals(totals), sessions)
|
|
603
|
+
block = _cli_usage_block(provider, _aggregate_totals(totals), sessions)
|
|
603
604
|
|
|
604
605
|
block["cliExecutionStatus"] = execution["status"]
|
|
605
606
|
if fallback_window_used:
|
|
@@ -624,6 +625,51 @@ def _worker_cli_windows(
|
|
|
624
625
|
return fallback_windows, status_path, True
|
|
625
626
|
|
|
626
627
|
|
|
628
|
+
def _antigravity_log_paths(
|
|
629
|
+
project_root: Path,
|
|
630
|
+
worker: dict,
|
|
631
|
+
status_path: Path | None,
|
|
632
|
+
) -> list[Path]:
|
|
633
|
+
"""agy stream-json 은 워커 로그에 남는다. 홈 세션 디렉터리가 아니다."""
|
|
634
|
+
paths: list[Path] = []
|
|
635
|
+
prompt_path = _resolve_project_path(project_root, str(worker.get("promptPath") or ""))
|
|
636
|
+
if prompt_path is not None:
|
|
637
|
+
log_path = log_path_for_prompt(prompt_path)
|
|
638
|
+
if log_path.is_file():
|
|
639
|
+
paths.append(log_path)
|
|
640
|
+
status = read_wrapper_status(status_path) if status_path else None
|
|
641
|
+
if status is not None and status.log_path is not None and status.log_path.is_file():
|
|
642
|
+
if status.log_path not in paths:
|
|
643
|
+
paths.append(status.log_path)
|
|
644
|
+
return paths
|
|
645
|
+
|
|
646
|
+
|
|
647
|
+
def _worker_cli_usage_block(
|
|
648
|
+
*,
|
|
649
|
+
provider: str,
|
|
650
|
+
project_root: Path,
|
|
651
|
+
worker: dict,
|
|
652
|
+
fallback_windows: list[tuple[str, str]],
|
|
653
|
+
) -> dict:
|
|
654
|
+
"""공급자 프로세스 트랜스크립트와 실행 증거로 워커 사용량 블록을 만든다."""
|
|
655
|
+
windows, status_path, used_fallback = _worker_cli_windows(
|
|
656
|
+
project_root,
|
|
657
|
+
worker,
|
|
658
|
+
fallback_windows,
|
|
659
|
+
)
|
|
660
|
+
session_paths = _cli_sessions_for_windows(provider, project_root, windows)
|
|
661
|
+
if provider == "antigravity":
|
|
662
|
+
for log_path in _antigravity_log_paths(project_root, worker, status_path):
|
|
663
|
+
if log_path not in session_paths:
|
|
664
|
+
session_paths.append(log_path)
|
|
665
|
+
return collect_cli_usage(
|
|
666
|
+
provider=provider,
|
|
667
|
+
status_path=status_path,
|
|
668
|
+
sessions=session_paths,
|
|
669
|
+
fallback_window_used=used_fallback,
|
|
670
|
+
)
|
|
671
|
+
|
|
672
|
+
|
|
627
673
|
def _attach_cli_usage(
|
|
628
674
|
block: dict,
|
|
629
675
|
provider: str,
|
|
@@ -638,8 +684,8 @@ def _attach_cli_usage(
|
|
|
638
684
|
window produces several rollout jsonls; pricing only the latest (the old
|
|
639
685
|
``find_codex_session`` -> ``sessions[-1]`` behavior) dropped the earlier
|
|
640
686
|
attempts' tokens. We sum every in-window session here so the redispatched
|
|
641
|
-
CLI spend is fully reported.
|
|
642
|
-
|
|
687
|
+
CLI spend is fully reported. antigravity 는 워커 로그의 stream-json
|
|
688
|
+
``result.usage`` 를 같은 합산 경로에 붙인다.
|
|
643
689
|
"""
|
|
644
690
|
session_paths = _cli_sessions_for_windows(provider, project_root, windows)
|
|
645
691
|
cli = collect_cli_usage(
|
|
@@ -676,17 +722,11 @@ def _collect_cli_runtime_usage(state: dict, project_root: Path) -> dict:
|
|
|
676
722
|
)
|
|
677
723
|
continue
|
|
678
724
|
worker_id = str(worker.get("workerId") or "").strip()
|
|
679
|
-
|
|
680
|
-
project_root,
|
|
681
|
-
worker,
|
|
682
|
-
windows_by_worker.get(worker_id, []),
|
|
683
|
-
)
|
|
684
|
-
session_paths = _cli_sessions_for_windows(provider, project_root, windows)
|
|
685
|
-
worker["usage"] = collect_cli_usage(
|
|
725
|
+
worker["usage"] = _worker_cli_usage_block(
|
|
686
726
|
provider=provider,
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
727
|
+
project_root=project_root,
|
|
728
|
+
worker=worker,
|
|
729
|
+
fallback_windows=windows_by_worker.get(worker_id, []),
|
|
690
730
|
)
|
|
691
731
|
_populate_usage_summary(state, team_name=resolve_team_name(state),
|
|
692
732
|
sessions_found=0, needle_source="none")
|
|
@@ -871,6 +911,7 @@ def collect_claude_runtime_usage(
|
|
|
871
911
|
sessions_dir = claude_project_dir(cwd)
|
|
872
912
|
# sid 로 귀속한 세션 id 전체 — 아래 unattributed 폴드에서 빼는 데 쓴다.
|
|
873
913
|
attributed_sids: set[str] = set()
|
|
914
|
+
cli_windows_by_worker = _codex_worker_windows(cwd, state)
|
|
874
915
|
for worker in state.get("workers", []):
|
|
875
916
|
worker_id = worker.get("workerId")
|
|
876
917
|
agent = worker.get("agent")
|
|
@@ -922,10 +963,21 @@ def collect_claude_runtime_usage(
|
|
|
922
963
|
matched_sids.add(entry[0])
|
|
923
964
|
|
|
924
965
|
if not matched:
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
966
|
+
provider = _cli_assignment_provider(worker)
|
|
967
|
+
if provider and str(worker.get("runner") or "") == "cli-wrapper":
|
|
968
|
+
worker["usage"] = _worker_cli_usage_block(
|
|
969
|
+
provider=provider,
|
|
970
|
+
project_root=cwd,
|
|
971
|
+
worker=worker,
|
|
972
|
+
fallback_windows=cli_windows_by_worker.get(
|
|
973
|
+
str(worker_id or "").strip(), []
|
|
974
|
+
),
|
|
975
|
+
)
|
|
976
|
+
else:
|
|
977
|
+
worker["usage"] = na_block(
|
|
978
|
+
"no Claude session jsonl in the run window for dispatched "
|
|
979
|
+
f"sessionIds {dispatched_sids} or agentName prefixes {prefixes}"
|
|
980
|
+
)
|
|
929
981
|
continue
|
|
930
982
|
|
|
931
983
|
# Stable order by startedAt so the "primary" session is the first one.
|
|
@@ -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,}$"
|