agent-tune-kit 2.3.0__tar.gz → 2.3.1__tar.gz
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.
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/.codex-plugin/plugin.json +1 -1
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/PKG-INFO +9 -5
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/README.en.md +8 -4
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/README.md +8 -4
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/__init__.py +1 -1
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/installer.py +47 -13
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/traces/query.py +10 -7
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/traces/records.py +7 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/traces/segments.py +3 -17
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/visualize/assets/trace/app.js +120 -20
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/visualize/assets/trace/page.html +1 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/visualize/assets/trace/styles.css +13 -0
- agent_tune_kit-2.3.1/agent_tune_kit/visualize/assets/trace/vendor/markdown-it.LICENSE +158 -0
- agent_tune_kit-2.3.1/agent_tune_kit/visualize/assets/trace/vendor/markdown-it.min.js +13 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/visualize/timeline.py +2 -12
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/visualize/trace.py +54 -3
- agent_tune_kit-2.3.1/docs/assets/agent_tune_kit_evaluation.png +0 -0
- agent_tune_kit-2.3.1/docs/assets/agent_tune_kit_trace.png +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/docs/shared-versioning-and-confirmation.md +2 -2
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/docs/skill-template-pack-usage.md +10 -7
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/docs/trace-tuning-validation.md +15 -1
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/docs/trace-tuning.md +14 -2
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/pyproject.toml +1 -1
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/scripts/check-release.py +1 -1
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/scripts/dev-refresh-install.sh +1 -1
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/scripts/validate_skill_pack.py +3 -1
- agent_tune_kit-2.3.1/skills/atk-trace-detect/SKILL.md +78 -0
- agent_tune_kit-2.3.1/skills/atk-trace-diagnose/SKILL.md +59 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/conftest.py +1 -1
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/test_install_plugin.py +12 -9
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/test_plugin_cache.py +88 -23
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/test_release_scripts.py +1 -1
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/test_trace_cli.py +2 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/test_trace_records.py +41 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/test_visualize_trace.py +142 -1
- agent_tune_kit-2.3.1/tests/trace-selection-reason.cjs +41 -0
- agent_tune_kit-2.3.0/skills/atk-trace-detect/SKILL.md +0 -57
- agent_tune_kit-2.3.0/skills/atk-trace-diagnose/SKILL.md +0 -47
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/.gitignore +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/cli/__init__.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/cli/__main__.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/cli/dataset.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/cli/evaluation.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/cli/main.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/cli/output.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/cli/results.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/cli/trace.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/cli/visualize.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/datasets/__init__.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/datasets/prepare.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/datasets/truth.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/datasets/updates.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/datasets/validation.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/errors.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/execution/__init__.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/execution/calibration.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/execution/logs.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/execution/rules.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/execution/runner.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/execution/runtime.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/execution/tracing.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/results/__init__.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/results/assessment.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/results/evidence.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/results/judgments.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/results/summary.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/results/versions.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/traces/__init__.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/traces/archive.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/traces/capture.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/traces/langfuse.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/traces/migrate.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/traces/store.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/utils/__init__.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/utils/csv_io.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/utils/files.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/visualize/__init__.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/visualize/assets/dataset/app.js +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/visualize/assets/dataset/page.html +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/visualize/assets/dataset/styles.css +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/visualize/assets/dataset/vendor/echarts.min.js +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/visualize/assets/failures/app.js +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/visualize/assets/failures/page.html +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/visualize/assets/failures/styles.css +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/visualize/assets/trace/lanes.js +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/visualize/dataset.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/visualize/failures.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/visualize/fields.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/visualize/history.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/visualize/render.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/workspace.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/docs/assets/arch-en.png +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/docs/assets/arch.png +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/docs/assets/architecture.en.svg +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/docs/assets/architecture.svg +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/docs/ato-atk-project-boundary-recommendation-2026-11-05.md +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/docs/cli-skill-modularization-plan.md +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/docs/codex_agent_tuning_prd.md +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/docs/execution-evidence-and-tracing-plan.md +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/docs/ground-truth-and-grading-assessment-2026-10-25.md +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/docs/local-context.md +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/docs/surginame-atk-capability-review-2026-10-27.md +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/docs/trace-swimlane-design.md +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/docs/truth-and-assessment.md +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/scripts/install_plugin.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/scripts/publish-pypi.sh +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/scripts/publish-release.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/scripts/release-version.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/scripts/release-version.sh +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/skills/atk-dataset/SKILL.md +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/skills/atk-dataset/scripts/update_dataset.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/skills/atk-diagnose/SKILL.md +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/skills/atk-eval/SKILL.md +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/skills/atk-init/SKILL.md +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/skills/atk-optimize/SKILL.md +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/skills/atk-report/SKILL.md +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/skills/atk-trace-capture/SKILL.md +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/skills/atk-trace-init/SKILL.md +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/skills/atk-trace-optimize/SKILL.md +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/skills/atk-trace-verify/SKILL.md +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/skills/atk-visualize-dataset/SKILL.md +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/skills/atk-visualize-dataset/scripts/generate_dataset_browser.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/skills/atk-visualize-failures/SKILL.md +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/skills/atk-visualize-failures/scripts/generate_failure_browser.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/skills/atk-visualize-trace/SKILL.md +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/templates/.atk/runner/eval_runner.py.md +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/templates/.atk/runner/failure_rule.py.md +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/templates/.atk/runner/import_evidence.py.md +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/templates/.gitkeep +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/__init__.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/fixtures/legacy_eval_runner.py.txt +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/fixtures/managed_v1.py.md +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/test_assessment_contract.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/test_atk_init_contract.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/test_cli_workflow.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/test_dataset_updates.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/test_diagnosis.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/test_evidence_import.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/test_evidence_judgments.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/test_evidence_packaging.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/test_evidence_versions.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/test_execution_evidence.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/test_execution_outcomes.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/test_execution_tracing.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/test_generate_dataset_browser.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/test_generate_failure_browser.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/test_judge_calibration.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/test_local_context.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/test_runner_output_columns.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/test_runner_template_row_logging.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/test_runtime_contracts.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/test_snapshot_reads.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/test_trace_capture.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/test_trace_langfuse.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/test_trace_query.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/test_trace_segments.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/test_trace_store.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/test_truth_browser.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/test_truth_cli.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/test_truth_contract.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/test_truth_runner.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/test_v2_progress.py +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/trace-event-wheel.cjs +0 -0
- {agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/tests/trace-preview-scroll.cjs +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-tune-kit",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.1",
|
|
4
4
|
"description": "Local Codex plugin for batch Agent evaluation and session trace tuning with evidence-backed issues, focused changes, verification and offline review.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "hustyichi",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: agent-tune-kit
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.1
|
|
4
4
|
Summary: Local Codex plugin for iterative Agent tuning with guided Skills, reusable runner templates, versioned results, and static validation.
|
|
5
5
|
Project-URL: Homepage, https://github.com/hustyichi/agent-tune-kit
|
|
6
6
|
Project-URL: Repository, https://github.com/hustyichi/agent-tune-kit
|
|
@@ -53,10 +53,12 @@ atk install
|
|
|
53
53
|
|
|
54
54
|
</details>
|
|
55
55
|
|
|
56
|
-
Finish active ATK tasks before reinstalling
|
|
56
|
+
Finish active ATK tasks before reinstalling. `atk install` directly updates and verifies the Codex ATK cache, so no cache rebuild is needed afterward. Start a new session to replace instructions already read into a conversation; restart Codex if the skill list has not refreshed. If you have installation problems, run `atk status` and confirm the plugin is enabled in Codex. [Installation and cache notes](docs/skill-template-pack-usage.md#local-plugin-install-and-smoke)
|
|
57
57
|
|
|
58
58
|
## Evaluation-based tuning
|
|
59
59
|
|
|
60
|
+

|
|
61
|
+
|
|
60
62
|
Use a set of evaluation samples to find Agent failures and verify changes in later rounds. Prepare your Agent's entry point and a set of samples, preferably in CSV format. Five to twenty samples are enough to get started. Add expected answers, labels, or acceptance criteria where available.
|
|
61
63
|
|
|
62
64
|
Open your Agent project in Codex and send the following `$atk-…` instructions in the conversation.
|
|
@@ -139,10 +141,10 @@ Each round saves results under `.atk/results/vN/` in your Agent project. Files a
|
|
|
139
141
|
|
|
140
142
|
[More batch evaluation options and outputs](docs/skill-template-pack-usage.md#manual-22--26-loop)
|
|
141
143
|
|
|
142
|
-

|
|
143
|
-
|
|
144
144
|
## Continuous tuning from session traces
|
|
145
145
|
|
|
146
|
+

|
|
147
|
+
|
|
146
148
|
Start with an existing session and use its execution trace to check whether the Agent completed the task. Save diagnoses, fixes, and verification results by issue. Get the native Session ID, its source, and access to the trace, then open the Agent project in Codex. You can start without an evaluation dataset or runner.
|
|
147
149
|
|
|
148
150
|
Run `atk trace --help` to check whether your CLI supports trace tuning. If the command is unavailable, follow the local source installation steps above with a version that supports trace tuning, then open a new Codex session.
|
|
@@ -161,7 +163,9 @@ $atk-trace-detect Check whether session <session-id> completed its task correctl
|
|
|
161
163
|
$atk-visualize-trace Open the execution lanes for session <session-id> and jump from issues to the relevant trace segments and evidence fields.
|
|
162
164
|
```
|
|
163
165
|
|
|
164
|
-
Detection
|
|
166
|
+
Detection retains issues with serious impact, recurrence, direct relevance to your stated focus, or a concrete implementation improvement lead, and explains the retention reason, evidence and inspection scope. Implementation leads include code, configuration, tool contracts, Prompt and Skill; an unresolved cause can proceed to diagnosis. Minor observations with none of these reasons are not saved separately. No retained issues does not prove the session was correct.
|
|
167
|
+
|
|
168
|
+
Use Trace IDs to locate evidence within the session and open issue details to read the retention reason. You can generate a preview once traces are archived. Review any retained content in the HTML before sharing it.
|
|
165
169
|
|
|
166
170
|
### 3. Investigate, Fix, and Verify an Issue as Needed
|
|
167
171
|
|
|
@@ -39,10 +39,12 @@ atk install
|
|
|
39
39
|
|
|
40
40
|
</details>
|
|
41
41
|
|
|
42
|
-
Finish active ATK tasks before reinstalling
|
|
42
|
+
Finish active ATK tasks before reinstalling. `atk install` directly updates and verifies the Codex ATK cache, so no cache rebuild is needed afterward. Start a new session to replace instructions already read into a conversation; restart Codex if the skill list has not refreshed. If you have installation problems, run `atk status` and confirm the plugin is enabled in Codex. [Installation and cache notes](docs/skill-template-pack-usage.md#local-plugin-install-and-smoke)
|
|
43
43
|
|
|
44
44
|
## Evaluation-based tuning
|
|
45
45
|
|
|
46
|
+

|
|
47
|
+
|
|
46
48
|
Use a set of evaluation samples to find Agent failures and verify changes in later rounds. Prepare your Agent's entry point and a set of samples, preferably in CSV format. Five to twenty samples are enough to get started. Add expected answers, labels, or acceptance criteria where available.
|
|
47
49
|
|
|
48
50
|
Open your Agent project in Codex and send the following `$atk-…` instructions in the conversation.
|
|
@@ -125,10 +127,10 @@ Each round saves results under `.atk/results/vN/` in your Agent project. Files a
|
|
|
125
127
|
|
|
126
128
|
[More batch evaluation options and outputs](docs/skill-template-pack-usage.md#manual-22--26-loop)
|
|
127
129
|
|
|
128
|
-

|
|
129
|
-
|
|
130
130
|
## Continuous tuning from session traces
|
|
131
131
|
|
|
132
|
+

|
|
133
|
+
|
|
132
134
|
Start with an existing session and use its execution trace to check whether the Agent completed the task. Save diagnoses, fixes, and verification results by issue. Get the native Session ID, its source, and access to the trace, then open the Agent project in Codex. You can start without an evaluation dataset or runner.
|
|
133
135
|
|
|
134
136
|
Run `atk trace --help` to check whether your CLI supports trace tuning. If the command is unavailable, follow the local source installation steps above with a version that supports trace tuning, then open a new Codex session.
|
|
@@ -147,7 +149,9 @@ $atk-trace-detect Check whether session <session-id> completed its task correctl
|
|
|
147
149
|
$atk-visualize-trace Open the execution lanes for session <session-id> and jump from issues to the relevant trace segments and evidence fields.
|
|
148
150
|
```
|
|
149
151
|
|
|
150
|
-
Detection
|
|
152
|
+
Detection retains issues with serious impact, recurrence, direct relevance to your stated focus, or a concrete implementation improvement lead, and explains the retention reason, evidence and inspection scope. Implementation leads include code, configuration, tool contracts, Prompt and Skill; an unresolved cause can proceed to diagnosis. Minor observations with none of these reasons are not saved separately. No retained issues does not prove the session was correct.
|
|
153
|
+
|
|
154
|
+
Use Trace IDs to locate evidence within the session and open issue details to read the retention reason. You can generate a preview once traces are archived. Review any retained content in the HTML before sharing it.
|
|
151
155
|
|
|
152
156
|
### 3. Investigate, Fix, and Verify an Issue as Needed
|
|
153
157
|
|
|
@@ -39,10 +39,12 @@ atk install
|
|
|
39
39
|
|
|
40
40
|
</details>
|
|
41
41
|
|
|
42
|
-
重装前先结束正在运行的 ATK
|
|
42
|
+
重装前先结束正在运行的 ATK 任务。`atk install` 会直接更新并校验 Codex 的 ATK 缓存,完成后无需等待缓存重建。已读入对话的旧指令仍需新建会话加载;技能列表未刷新时重启 Codex。遇到安装问题时,运行 `atk status` 检查安装,并在 Codex 中确认插件已启用。[安装与缓存说明](docs/skill-template-pack-usage.md#local-plugin-install-and-smoke)
|
|
43
43
|
|
|
44
44
|
## 评测调优
|
|
45
45
|
|
|
46
|
+

|
|
47
|
+
|
|
46
48
|
用一组评测样本找出 Agent 的问题,并用后续评测验证改动。准备 Agent 的入口和一组样本,推荐用 CSV,5 到 20 条即可开始。每条样本可附上期望答案、标签或可验收的行为标准。
|
|
47
49
|
|
|
48
50
|
在 Codex 中打开 Agent 项目,在对话中发送下面的 `$atk-…` 指令。
|
|
@@ -125,10 +127,10 @@ $atk-report
|
|
|
125
127
|
|
|
126
128
|
[更多批量评测运行选项和产物](docs/skill-template-pack-usage.md#manual-22--26-loop)
|
|
127
129
|
|
|
128
|
-

|
|
129
|
-
|
|
130
130
|
## 轨迹持续调优
|
|
131
131
|
|
|
132
|
+

|
|
133
|
+
|
|
132
134
|
从一个已有会话出发,结合实际执行轨迹判断任务是否完成,再按问题保存诊断、修复和验证记录。准备原始 Session ID、来源和可读取的轨迹,直接在 Codex 中打开 Agent 项目开始。无需评测数据集或 runner。
|
|
133
135
|
|
|
134
136
|
可用 `atk trace --help` 检查当前 CLI 是否支持轨迹调优。如果命令不可用,按上面的本地源码方式安装支持轨迹调优的版本,再新建 Codex 会话。
|
|
@@ -147,7 +149,9 @@ $atk-trace-detect 分析 <session-id> 的任务结果是否正确,列出问题
|
|
|
147
149
|
$atk-visualize-trace 打开 <session-id> 的执行泳道,从问题跳到相关轨迹片段和证据字段。
|
|
148
150
|
```
|
|
149
151
|
|
|
150
|
-
|
|
152
|
+
分析保留影响严重、反复出现、与你明确关注点相关,或有具体实现改进线索的问题,并说明保留理由、证据和检查范围。实现线索包括代码、配置、工具契约、Prompt 和 Skill;根因尚未确定也可进入后续诊断。轻微且无上述保留理由的观察不单独记录,没有保留问题不代表会话完全正确。
|
|
153
|
+
|
|
154
|
+
可用 Trace ID 定位会话内的证据,在问题详情中查看保留理由。有归档轨迹即可生成预览,分享 HTML 前请核对其中留存的正文。
|
|
151
155
|
|
|
152
156
|
### 3. 按问题调查、修复和验证(按需)
|
|
153
157
|
|
|
@@ -406,9 +406,8 @@ def cache_status(target: Path, cache: Path) -> tuple[bool, list[str]]:
|
|
|
406
406
|
entries = sorted(cache.iterdir()) if cache.exists() else []
|
|
407
407
|
entries = [entry for entry in entries if entry.name not in COPY_IGNORE_NAMES]
|
|
408
408
|
if not entries:
|
|
409
|
-
return
|
|
409
|
+
return False, ["ATK 缓存缺失;运行 atk install 修复。"]
|
|
410
410
|
expected = payload_hashes(target)
|
|
411
|
-
version = current_manifest_version(target)
|
|
412
411
|
ok = True
|
|
413
412
|
lines: list[str] = []
|
|
414
413
|
for entry in entries:
|
|
@@ -418,22 +417,57 @@ def cache_status(target: Path, cache: Path) -> tuple[bool, list[str]]:
|
|
|
418
417
|
missing = sorted(expected.keys() - actual.keys())
|
|
419
418
|
extra = sorted(actual.keys() - expected.keys())
|
|
420
419
|
changed = sorted(key for key in expected.keys() & actual.keys() if expected[key] != actual[key])
|
|
421
|
-
|
|
422
|
-
if not (missing or extra or changed) and version_ok:
|
|
420
|
+
if not (missing or extra or changed):
|
|
423
421
|
lines.append(f"缓存与安装内容一致:{entry}")
|
|
424
422
|
continue
|
|
425
423
|
ok = False
|
|
426
424
|
lines.append(f"缓存不一致:{entry}(修改 {len(changed)},缺失 {len(missing)},多余 {len(extra)})")
|
|
427
|
-
if not version_ok:
|
|
428
|
-
lines.append(f" 缓存目录版本 {entry.name} 与安装版本 {version} 不同。")
|
|
429
425
|
differences = [("修改", changed), ("缺失", missing), ("多余", extra)]
|
|
430
426
|
details = [f" {label}:{name}" for label, names in differences for name in names]
|
|
431
427
|
lines.extend(details[:5])
|
|
432
428
|
if not ok:
|
|
433
|
-
lines.append("运行 atk install
|
|
429
|
+
lines.append("运行 atk install 更新缓存;已读入的旧指令需新建会话,技能列表未刷新时重启 Codex。")
|
|
434
430
|
return ok, lines
|
|
435
431
|
|
|
436
432
|
|
|
433
|
+
def refresh_plugin_cache(target: Path, cache: Path, payload_source: PayloadSource) -> None:
|
|
434
|
+
entries = [entry for entry in cache.iterdir() if entry.name not in COPY_IGNORE_NAMES] if cache.exists() else []
|
|
435
|
+
for entry in entries:
|
|
436
|
+
if entry.is_symlink() or not entry.is_dir():
|
|
437
|
+
raise InstallError(f"unsafe plugin cache entry: {entry}")
|
|
438
|
+
|
|
439
|
+
cache.parent.mkdir(parents=True, exist_ok=True)
|
|
440
|
+
work = Path(tempfile.mkdtemp(prefix=f".{PLUGIN_NAME}-", dir=cache.parent))
|
|
441
|
+
staged, previous = work / "new", work / "previous"
|
|
442
|
+
try:
|
|
443
|
+
copy_payload_tree(payload_source, staged / "local")
|
|
444
|
+
# Keep paths already advertised to sessions readable with the new payload.
|
|
445
|
+
for entry in entries:
|
|
446
|
+
if entry.name != "local":
|
|
447
|
+
shutil.copytree(staged / "local", staged / entry.name)
|
|
448
|
+
valid, details = cache_status(target, staged)
|
|
449
|
+
if not valid:
|
|
450
|
+
raise InstallError("staged cache validation failed: " + "; ".join(details))
|
|
451
|
+
|
|
452
|
+
# shortcut: two renames leave a brief gap; use a platform directory exchange if live-read continuity is required.
|
|
453
|
+
if cache.exists():
|
|
454
|
+
os.replace(cache, previous)
|
|
455
|
+
try:
|
|
456
|
+
os.replace(staged, cache)
|
|
457
|
+
except BaseException:
|
|
458
|
+
if previous.exists():
|
|
459
|
+
try:
|
|
460
|
+
os.replace(previous, cache)
|
|
461
|
+
except OSError as exc:
|
|
462
|
+
raise InstallError(f"cache restore failed; previous cache preserved at {previous}: {exc}") from exc
|
|
463
|
+
raise
|
|
464
|
+
remove_path(previous)
|
|
465
|
+
finally:
|
|
466
|
+
# A failed restore must not delete the only surviving previous cache.
|
|
467
|
+
if not previous.exists():
|
|
468
|
+
remove_path(work)
|
|
469
|
+
|
|
470
|
+
|
|
437
471
|
def collect_status(
|
|
438
472
|
marketplace_path: Path, plugin_store: Path, payload_source: PayloadSource | None = None
|
|
439
473
|
) -> tuple[dict[str, bool], list[str]]:
|
|
@@ -561,7 +595,7 @@ def run_preview(args: argparse.Namespace) -> int:
|
|
|
561
595
|
print("已有文件或注册与本次安装冲突;替换需要确认。")
|
|
562
596
|
if args.smoke:
|
|
563
597
|
smoke_check(marketplace_path, plugin_store, dry_run=True, payload_source=payload_source)
|
|
564
|
-
print(f"
|
|
598
|
+
print(f"安装校验成功后将更新 ATK 缓存:{cache}")
|
|
565
599
|
print("未修改文件。运行 atk install 进行安装。")
|
|
566
600
|
return 0
|
|
567
601
|
|
|
@@ -595,16 +629,16 @@ def run_install(args: argparse.Namespace) -> int:
|
|
|
595
629
|
smoke_check(marketplace_path, plugin_store, dry_run=False, payload_source=payload_source)
|
|
596
630
|
|
|
597
631
|
validate_manifest(target / ".codex-plugin" / "plugin.json")
|
|
598
|
-
#
|
|
632
|
+
# Publish only after a usable installation exists, including with --no-smoke.
|
|
599
633
|
try:
|
|
600
634
|
cache = plugin_cache_path(target, marketplace_path, payload_source)
|
|
601
|
-
|
|
635
|
+
refresh_plugin_cache(target, cache, payload_source)
|
|
602
636
|
except (InstallError, OSError) as exc:
|
|
603
637
|
raise InstallError(f"plugin installed, but cache refresh failed: {cache}: {exc}") from exc
|
|
604
638
|
|
|
605
639
|
print(f"已为 Codex 本地安装 Agent Tune Kit {payload_source.package_version}。")
|
|
606
|
-
print("ATK
|
|
607
|
-
print("
|
|
640
|
+
print("ATK 缓存已更新并校验,后续文件读取使用最新内容。")
|
|
641
|
+
print("下一步:确认 Codex /plugins 已启用 Agent Tune Kit;已读入的旧指令需新建会话,技能列表未刷新时重启 Codex。")
|
|
608
642
|
return 0
|
|
609
643
|
|
|
610
644
|
|
|
@@ -691,7 +725,7 @@ def parse_args(argv: list[str]) -> argparse.Namespace:
|
|
|
691
725
|
subparsers.add_parser(
|
|
692
726
|
"preview", parents=[common], help="preview planned marketplace/plugin-store changes without writing"
|
|
693
727
|
)
|
|
694
|
-
subparsers.add_parser("install", parents=[common], help="install, validate, then
|
|
728
|
+
subparsers.add_parser("install", parents=[common], help="install, validate, then replace personal ATK caches")
|
|
695
729
|
subparsers.add_parser(
|
|
696
730
|
"status", parents=[common], help="check local installation and compare cached plugin contents (read-only)"
|
|
697
731
|
)
|
|
@@ -10,12 +10,12 @@ from agent_tune_kit.errors import UserActionRequired
|
|
|
10
10
|
from . import store
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
def
|
|
13
|
+
def timestamp_ms(value):
|
|
14
|
+
"""Parse epoch milliseconds, interpreting unzoned timestamps as machine-local time."""
|
|
14
15
|
if isinstance(value, str):
|
|
15
16
|
try:
|
|
16
17
|
moment = datetime.fromisoformat(value)
|
|
17
|
-
|
|
18
|
-
return round(moment.timestamp() * 1_000_000) / 1000
|
|
18
|
+
return round(moment.timestamp() * 1_000_000) / 1000
|
|
19
19
|
except (ValueError, OSError, OverflowError):
|
|
20
20
|
pass
|
|
21
21
|
return None
|
|
@@ -180,17 +180,20 @@ def overview(session_dir, capture_id=None, offset=0, limit=100, trace_id=None):
|
|
|
180
180
|
ordered = sorted(
|
|
181
181
|
items,
|
|
182
182
|
key=lambda item: (
|
|
183
|
-
|
|
184
|
-
|
|
183
|
+
timestamp_ms(item.get("start_time")) is None,
|
|
184
|
+
timestamp_ms(item.get("start_time")) if timestamp_ms(item.get("start_time")) is not None else inf,
|
|
185
185
|
str(item.get("trace_id") or ""),
|
|
186
186
|
str(item.get("id") or ""),
|
|
187
187
|
),
|
|
188
188
|
)
|
|
189
|
-
session_start = next(
|
|
189
|
+
session_start = next(
|
|
190
|
+
(timestamp_ms(item.get("start_time")) for item in ordered if timestamp_ms(item.get("start_time")) is not None),
|
|
191
|
+
None,
|
|
192
|
+
)
|
|
190
193
|
|
|
191
194
|
def row(item):
|
|
192
195
|
summary = _summary(item)
|
|
193
|
-
at =
|
|
196
|
+
at = timestamp_ms(item.get("start_time"))
|
|
194
197
|
summary["node_id"] = item.get("id")
|
|
195
198
|
summary["parent_id"] = item.get("parent_id")
|
|
196
199
|
summary["session_offset_ms"] = None if session_start is None or at is None else at - session_start
|
|
@@ -138,6 +138,10 @@ def prepare_issue(session_dir, data, *, dry_run=False):
|
|
|
138
138
|
data = copy.deepcopy(data)
|
|
139
139
|
if not isinstance(data, dict):
|
|
140
140
|
raise UserActionRequired("Issue data must be an object.")
|
|
141
|
+
if "selection_reason" in data and (
|
|
142
|
+
not isinstance(data["selection_reason"], str) or not data["selection_reason"].strip()
|
|
143
|
+
):
|
|
144
|
+
raise UserActionRequired("Issue selection_reason must be a non-empty string when supplied.")
|
|
141
145
|
issue_id = data.get("id", data.get("issue_id"))
|
|
142
146
|
if issue_id is None:
|
|
143
147
|
number = 1
|
|
@@ -215,6 +219,7 @@ def prepare_issue(session_dir, data, *, dry_run=False):
|
|
|
215
219
|
"updated_at",
|
|
216
220
|
"title",
|
|
217
221
|
"description",
|
|
222
|
+
"selection_reason",
|
|
218
223
|
"evidence",
|
|
219
224
|
"segments",
|
|
220
225
|
"status",
|
|
@@ -331,6 +336,8 @@ def save_diagnosis(session_dir, issue_id, text, diagnosis_id=None):
|
|
|
331
336
|
"segments": issue.get("segments", []),
|
|
332
337
|
"created_at": now(),
|
|
333
338
|
}
|
|
339
|
+
if "selection_reason" in issue:
|
|
340
|
+
snapshot["selection_reason"] = issue["selection_reason"]
|
|
334
341
|
_refs(directory, issue["evidence"])
|
|
335
342
|
for segment in snapshot["segments"]:
|
|
336
343
|
_refs(directory, segment["evidence"])
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
from collections import defaultdict
|
|
6
|
-
from datetime import datetime
|
|
7
6
|
from math import inf
|
|
8
7
|
|
|
9
8
|
from agent_tune_kit.errors import UserActionRequired
|
|
@@ -12,17 +11,6 @@ from . import query
|
|
|
12
11
|
from .store import validate_ref
|
|
13
12
|
|
|
14
13
|
|
|
15
|
-
def _milliseconds(value):
|
|
16
|
-
if isinstance(value, str):
|
|
17
|
-
try:
|
|
18
|
-
moment = datetime.fromisoformat(value)
|
|
19
|
-
if moment.utcoffset() is not None:
|
|
20
|
-
return round(moment.timestamp() * 1_000_000) / 1000
|
|
21
|
-
except (ValueError, OSError, OverflowError):
|
|
22
|
-
pass
|
|
23
|
-
return None
|
|
24
|
-
|
|
25
|
-
|
|
26
14
|
def _node_pointer(pointer):
|
|
27
15
|
if not isinstance(pointer, str) or not pointer:
|
|
28
16
|
return "", ""
|
|
@@ -74,8 +62,8 @@ def _index_nodes(session_dir):
|
|
|
74
62
|
if isinstance(identity, (str, int)):
|
|
75
63
|
slot = (node.get("trace_id"), identity)
|
|
76
64
|
by_identity[slot] = index if slot not in by_identity else None
|
|
77
|
-
at =
|
|
78
|
-
until =
|
|
65
|
+
at = query.timestamp_ms(node.get("start_time"))
|
|
66
|
+
until = query.timestamp_ms(node.get("end_time"))
|
|
79
67
|
if until is None or at is None or until < at:
|
|
80
68
|
until = at
|
|
81
69
|
node["at"] = at
|
|
@@ -218,9 +206,7 @@ def resolve_segments(session_dir, segments, *, assign_ids=True):
|
|
|
218
206
|
raise UserActionRequired(f"Segment {offset} from is later than to.")
|
|
219
207
|
low, high = rank[start_i], rank[end_i]
|
|
220
208
|
covered = {
|
|
221
|
-
i
|
|
222
|
-
for i in order[low : high + 1]
|
|
223
|
-
if nodes[i].get("trace_id") == nodes[start_i].get("trace_id")
|
|
209
|
+
i for i in order[low : high + 1] if nodes[i].get("trace_id") == nodes[start_i].get("trace_id")
|
|
224
210
|
}
|
|
225
211
|
else:
|
|
226
212
|
lo, hi = start_at, end_at
|
|
@@ -8,12 +8,16 @@
|
|
|
8
8
|
const button = (text, action, className) => { const node = el("button", text, className); node.type = "button"; node.onclick = action; return node; };
|
|
9
9
|
const pre = value => el("pre", pretty(value));
|
|
10
10
|
const section = (title, value) => { const node = el("section", undefined, "detail-section"); node.append(el("h3", title)); if (value !== undefined) node.append(pre(value)); return node; };
|
|
11
|
+
const markdown = window.markdownit({html:false});
|
|
12
|
+
markdown.renderer.rules.image = (tokens, index) => markdown.utils.escapeHtml(tokens[index].content);
|
|
13
|
+
const sourceLinks = new Map(Object.entries(data.diagnosis_source_links).map(([href, target]) => [markdown.normalizeLink(href), target]));
|
|
11
14
|
const options = (select, values, all) => { select.replaceChildren(); if (all !== undefined) { const item = el("option", all); item.value = ""; select.append(item); } for (const value of values) { const item = el("option", value); item.value = value; select.append(item); } };
|
|
12
15
|
const references = value => { const result = []; const seen = new Set(); const walk = item => { if (Array.isArray(item)) item.forEach(walk); else if (item && typeof item === "object") { if (typeof item.path === "string" && typeof item.sha256 === "string") { const key = refKey(item); if (!seen.has(key)) { seen.add(key); result.push(item); } } else Object.values(item).forEach(walk); } }; walk(value); return result; };
|
|
13
16
|
const RAIL_KEY = "atk-trace-rail-collapsed";
|
|
14
17
|
let currentCapture = data.captures.at(-1) || null;
|
|
15
18
|
let returnFocus = null, activeIssue = null, issueStage = "issue", drawerMode = null;
|
|
16
19
|
let selectedNode = null, origin = null, issueTrigger = null;
|
|
20
|
+
let returnToDiagnosis = null;
|
|
17
21
|
let investigation = null, scopeBefore = null, previewIssue = null, expandedFolds = new Set(), railFilter = null;
|
|
18
22
|
const captureById = new Map(data.captures.map(c => [c.id, c]));
|
|
19
23
|
const issueById = new Map(data.issues.map(item => [item.record.id, item]));
|
|
@@ -107,6 +111,7 @@
|
|
|
107
111
|
$("drawer").hidden = true;
|
|
108
112
|
drawerMode = null;
|
|
109
113
|
activeIssue = null; origin = null;
|
|
114
|
+
returnToDiagnosis = null;
|
|
110
115
|
if (restoreFocus && returnFocus?.isConnected) returnFocus.focus({preventScroll:true});
|
|
111
116
|
else if (restoreFocus && investigation) $("fragment-fields").focus({preventScroll:true});
|
|
112
117
|
else if (restoreFocus && issueTrigger) document.querySelector(`[data-issue-id="${CSS.escape(issueTrigger)}"]`)?.focus({preventScroll:true});
|
|
@@ -171,10 +176,8 @@
|
|
|
171
176
|
const content = record.record || record.text;
|
|
172
177
|
if (content !== undefined) {
|
|
173
178
|
if (typeof content === "string") {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
linkSegmentCites(body, content);
|
|
177
|
-
card.append(body);
|
|
179
|
+
card.firstElementChild.classList.add("diagnosis-path");
|
|
180
|
+
card.append(renderDiagnosis(content));
|
|
178
181
|
} else {
|
|
179
182
|
const summary = [];
|
|
180
183
|
for (const key of ["status", "target_issues", "candidate_loaded"]) if (content[key] !== undefined) summary.push(`${key}: ${pretty(content[key])}`);
|
|
@@ -189,22 +192,114 @@
|
|
|
189
192
|
appendReferences(card, record);
|
|
190
193
|
return card;
|
|
191
194
|
};
|
|
192
|
-
function
|
|
193
|
-
const
|
|
194
|
-
if (!
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
195
|
+
function appendDiagnoses(item) {
|
|
196
|
+
const container = $("drawer-content");
|
|
197
|
+
if (!item.diagnoses.length) {
|
|
198
|
+
container.append(el("p", "尚未记录诊断与修复/验证方案。", "empty"));
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
for (const [index, diagnosis] of item.diagnoses.slice().reverse().entries()) {
|
|
202
|
+
const body = diagnosis.error ? el("p", diagnosis.error, "warning") : renderDiagnosis(diagnosis.text);
|
|
203
|
+
const headings = [...body.children].filter(node => node.tagName === "H2").map(node => node.textContent);
|
|
204
|
+
const structured = headings.join("|") === "异常描述|异常根因|最小修复方案"
|
|
205
|
+
|| headings.join("|") === "Issue description|Root cause|Minimal fix";
|
|
206
|
+
if (index === 0 && structured) {
|
|
207
|
+
container.append(body);
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
if (index === 0) {
|
|
211
|
+
const description = section("异常描述");
|
|
212
|
+
description.append(el("p", item.record.description || item.record.title));
|
|
213
|
+
for (const [position, part] of item.fragments.entries()) {
|
|
214
|
+
const cite = button(part.id || `片段 ${position + 1}`, () => openDiagnosisSegment(item, position, cite), "diagnosis-cite");
|
|
215
|
+
description.append(cite);
|
|
216
|
+
}
|
|
217
|
+
container.append(description);
|
|
218
|
+
}
|
|
219
|
+
const details = el("details", undefined, "detail-section");
|
|
220
|
+
const name = diagnosis.reference.path.split("/").pop();
|
|
221
|
+
details.append(el("summary", `展开原诊断 · ${name}`), body);
|
|
222
|
+
container.append(details);
|
|
204
223
|
}
|
|
205
|
-
|
|
224
|
+
}
|
|
225
|
+
function renderDiagnosis(text) {
|
|
226
|
+
const body = el("div", undefined, "diagnosis-markdown");
|
|
227
|
+
const template = document.createElement("template");
|
|
228
|
+
template.innerHTML = markdown.render(text);
|
|
229
|
+
for (const link of template.content.querySelectorAll("a[href]")) {
|
|
230
|
+
const href = link.getAttribute("href");
|
|
231
|
+
const source = location.protocol === "file:" && sourceLinks.get(href);
|
|
232
|
+
if (source || /^https?:\/\//i.test(href)) {
|
|
233
|
+
if (source) link.setAttribute("href", source);
|
|
234
|
+
link.target = "_blank";
|
|
235
|
+
link.rel = "noopener noreferrer";
|
|
236
|
+
} else {
|
|
237
|
+
let path = href;
|
|
238
|
+
try { path = decodeURI(href); } catch { /* Keep malformed escape sequences as text. */ }
|
|
239
|
+
const locationText = el("code", path);
|
|
240
|
+
locationText.hidden = true;
|
|
241
|
+
const copy = button("复制路径", async () => {
|
|
242
|
+
try { await navigator.clipboard.writeText(path); copy.textContent = "已复制"; }
|
|
243
|
+
catch { locationText.hidden = false; }
|
|
244
|
+
});
|
|
245
|
+
link.replaceWith(...link.childNodes, " ", el("code", path.split("/").pop() || path), copy, locationText);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
for (const table of template.content.querySelectorAll("table")) {
|
|
249
|
+
const scroll = el("div", undefined, "diagnosis-table");
|
|
250
|
+
scroll.tabIndex = 0;
|
|
251
|
+
scroll.setAttribute("aria-label", "诊断表格");
|
|
252
|
+
table.before(scroll);
|
|
253
|
+
scroll.append(table);
|
|
254
|
+
}
|
|
255
|
+
body.append(template.content);
|
|
256
|
+
const walker = document.createTreeWalker(body, NodeFilter.SHOW_TEXT);
|
|
257
|
+
const nodes = [];
|
|
258
|
+
while (walker.nextNode()) {
|
|
259
|
+
const node = walker.currentNode;
|
|
260
|
+
if (node.data.includes("ISSUE-") && !node.parentElement.closest("pre, a")) nodes.push(node);
|
|
261
|
+
}
|
|
262
|
+
for (const node of nodes) {
|
|
263
|
+
const parts = document.createDocumentFragment();
|
|
264
|
+
let offset = 0;
|
|
265
|
+
for (const match of node.data.matchAll(/\b(ISSUE-\d+)\/(S\d+)\b/g)) {
|
|
266
|
+
const item = issueById.get(match[1]);
|
|
267
|
+
const index = item?.fragments.findIndex(part => part.id === match[2]);
|
|
268
|
+
if (index === undefined || index < 0) continue;
|
|
269
|
+
const cite = button(match[0], () => openDiagnosisSegment(item, index, cite), "diagnosis-cite");
|
|
270
|
+
parts.append(node.data.slice(offset, match.index), cite);
|
|
271
|
+
offset = match.index + match[0].length;
|
|
272
|
+
}
|
|
273
|
+
if (offset) {
|
|
274
|
+
parts.append(node.data.slice(offset));
|
|
275
|
+
node.replaceWith(parts);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return body;
|
|
279
|
+
}
|
|
280
|
+
function openDiagnosisSegment(item, index, trigger) {
|
|
281
|
+
const drawerContent = $("drawer-content");
|
|
282
|
+
const sourceIssue = activeIssue, view = rememberView(), priorScope = scopeBefore;
|
|
283
|
+
const previous = investigation && {...investigation};
|
|
284
|
+
const top = drawerContent.scrollTop;
|
|
285
|
+
const citeIndex = [...drawerContent.querySelectorAll(".diagnosis-cite")].indexOf(trigger);
|
|
286
|
+
returnToDiagnosis = () => {
|
|
287
|
+
investigation = previous;
|
|
288
|
+
scopeBefore = priorScope;
|
|
289
|
+
restoreView(view);
|
|
290
|
+
showIssue(sourceIssue, "diagnoses");
|
|
291
|
+
const restored = drawerContent.querySelectorAll(".diagnosis-cite")[citeIndex];
|
|
292
|
+
const details = restored?.closest("details");
|
|
293
|
+
if (details) details.open = true;
|
|
294
|
+
drawerContent.scrollTop = top;
|
|
295
|
+
restored?.focus({preventScroll:true});
|
|
296
|
+
};
|
|
297
|
+
startIssue(item, index);
|
|
298
|
+
origin = null;
|
|
299
|
+
showFragmentEvidence();
|
|
206
300
|
}
|
|
207
301
|
const showIssue = (item, stage = "issue") => {
|
|
302
|
+
returnToDiagnosis = null;
|
|
208
303
|
if (!activeIssue || activeIssue.record.id !== item.record.id) {
|
|
209
304
|
origin = null;
|
|
210
305
|
issueTrigger = item.record.id;
|
|
@@ -222,6 +317,11 @@
|
|
|
222
317
|
const description = section("问题描述");
|
|
223
318
|
description.append(el("p", issue.description || issue.title));
|
|
224
319
|
$("drawer-content").append(description);
|
|
320
|
+
if (typeof issue.selection_reason === "string" && issue.selection_reason.trim()) {
|
|
321
|
+
const reason = section("保留理由");
|
|
322
|
+
reason.append(el("p", issue.selection_reason));
|
|
323
|
+
$("drawer-content").append(reason);
|
|
324
|
+
}
|
|
225
325
|
const segments = issue.segments || [];
|
|
226
326
|
if (segments.length) {
|
|
227
327
|
const box = section("关联片段");
|
|
@@ -245,8 +345,7 @@
|
|
|
245
345
|
return;
|
|
246
346
|
}
|
|
247
347
|
if (stage === "diagnoses") {
|
|
248
|
-
|
|
249
|
-
for (const diagnosis of item.diagnoses) $("drawer-content").append(recordCard(diagnosis.reference.path, diagnosis));
|
|
348
|
+
appendDiagnoses(item);
|
|
250
349
|
} else if (stage === "changes") {
|
|
251
350
|
if (!item.changes.length) $("drawer-content").append(el("p", "尚未记录实际修改。局部检查不代表 Agent 效果验证。", "empty"));
|
|
252
351
|
for (const change of item.changes) $("drawer-content").append(recordCard(change.reference.path, change));
|
|
@@ -784,6 +883,7 @@
|
|
|
784
883
|
const part = item.fragments[index];
|
|
785
884
|
activeIssue = item; issueStage = "fragment"; issueTrigger = item.record.id;
|
|
786
885
|
openDrawer(`${item.record.id} · ${part.id || `片段 ${index+1}`} 的证据`, "issue");
|
|
886
|
+
if (returnToDiagnosis) $("drawer-content").append(button("← 返回诊断", returnToDiagnosis));
|
|
787
887
|
if (part.summary) $("drawer-content").append(el("p", part.summary, "muted"));
|
|
788
888
|
function add(title, positions) {
|
|
789
889
|
if (!positions?.length) return;
|
|
@@ -828,7 +928,7 @@
|
|
|
828
928
|
box.append(note);
|
|
829
929
|
}
|
|
830
930
|
if (!filtered.length) {
|
|
831
|
-
box.append(el("p", data.issues.length ? "没有符合筛选条件的问题。" : data.session.detections.length ? "
|
|
931
|
+
box.append(el("p", data.issues.length ? "没有符合筛选条件的问题。" : data.session.detections.length ? "已保存检测记录,尚无保留问题;请查看检查范围与缺口。" : "尚未进行异常识别。", "empty"));
|
|
832
932
|
return;
|
|
833
933
|
}
|
|
834
934
|
for (const item of filtered) {
|
{agent_tune_kit-2.3.0 → agent_tune_kit-2.3.1}/agent_tune_kit/visualize/assets/trace/styles.css
RENAMED
|
@@ -226,6 +226,19 @@ select:hover, .toolbar input:hover { border-color: #9baebb }
|
|
|
226
226
|
.detail-section { background: white; padding: 12px; border: 1px solid var(--line); border-radius: 7px; margin-block: 10px }
|
|
227
227
|
.detail-section h3 { margin-bottom: 6px }
|
|
228
228
|
.detail-section button { font-size: 12px; margin: 2px }
|
|
229
|
+
.detail-section .diagnosis-path { color: var(--muted); font-size: 12px; font-weight: 500 }
|
|
230
|
+
.diagnosis-markdown { line-height: 1.65 }
|
|
231
|
+
.diagnosis-markdown h1 { font-size: 19px; line-height: 1.4; margin: 12px 0 }
|
|
232
|
+
.diagnosis-markdown h2 { font-size: 16px; margin: 20px 0 8px }
|
|
233
|
+
.diagnosis-markdown p, .diagnosis-markdown ul, .diagnosis-markdown ol { margin: 8px 0 }
|
|
234
|
+
.diagnosis-markdown ul, .diagnosis-markdown ol { padding-inline-start: 24px }
|
|
235
|
+
.diagnosis-markdown li + li { margin-top: 6px }
|
|
236
|
+
.diagnosis-markdown blockquote { margin: 10px 0; padding-inline-start: 12px; border-inline-start: 3px solid var(--line) }
|
|
237
|
+
.diagnosis-table { overflow-x: auto; margin-block: 12px }
|
|
238
|
+
.diagnosis-markdown table { border-collapse: collapse; width: 100%; font-size: 13px }
|
|
239
|
+
.diagnosis-markdown th, .diagnosis-markdown td { border: 1px solid var(--line); padding: 6px 8px; vertical-align: top }
|
|
240
|
+
.diagnosis-markdown th { background: var(--bg); text-align: start }
|
|
241
|
+
.diagnosis-markdown .diagnosis-cite { padding: 1px 5px; color: var(--accent); font: inherit; font-size: .88em; white-space: nowrap }
|
|
229
242
|
.evidence-link { display: block; width: 100%; text-align: left; white-space: normal; overflow-wrap: anywhere }
|
|
230
243
|
.evidence-link strong, .evidence-link code { display: block }
|
|
231
244
|
.evidence-link code, #evidence-field>code { font-size: 12px; color: var(--muted) }
|