agent-apprenticeship 0.1.8 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,192 @@
1
+ # Agent Apprenticeship Trace Schema
2
+
3
+ ## Purpose
4
+
5
+ Agent Apprenticeship traces record authentic task work so completed workflows can become reusable agent experience. AgentTrace records observable workflow steps: task state, Apprentice Agent action, observed environment response, next state, artifacts produced, and evidence used by mentors, evaluators, verifiers, and graders.
6
+
7
+ Official quality labels come from mentor, expert, evaluator, verifier, and grader records, not from Apprentice Agent self-evaluation. This separation keeps the raw trace focused on what happened while outcome labels remain grounded in external evidence.
8
+
9
+ ## Public Product Model
10
+
11
+ Public task metadata uses `apprenticeship_mode`:
12
+
13
+ - `autonomous` for Autonomous Apprenticeship
14
+ - `expert_led` for Expert-Led Apprenticeship
15
+ - `org_custom` for Organization Custom
16
+
17
+ The older internal `mentor_mode` field may remain in legacy packages for compatibility, but public docs and new package metadata should prefer `apprenticeship_mode`. Mentor Model Providers, experts, evaluators, verifiers, and graders remain outcome evidence sources. Apprentice Agent self-assessment is not outcome truth.
18
+
19
+ ## Authentic Workflow Tracing
20
+
21
+ Trace real task work only. Do not trace Agent Apprenticeship packaging, public upload mechanics, or ecosystem storage steps as task work. Keep one meaningful action per step. Do not compress multiple actions into a vague paragraph. Preserve causality through `caused_by`, `causal_type`, and `causal_note`.
22
+
23
+ ## Canonical Outputs
24
+
25
+ `actual_outputs.json` is the canonical output contract. Traces should include `actual_outputs_ref` when known, plus `artifact_refs`, `deliverable_refs`, `files_created`, `output_summary`, and `final_output_summary` derived from actual outputs rather than copied raw deliverables.
26
+
27
+ Large files, screenshots, PDFs, tables, logs, audio, video, workbooks, and binary artifacts must be referenced through package-relative artifact refs. Do not embed huge binaries in JSON.
28
+
29
+ ## Observation, Input, Output, State Change
30
+
31
+ `observation` records what the agent saw before acting. `input` records the exact command, tool request, user instruction, artifact, or feedback used. `output` records the observed tool/environment response. `state_change` records what changed after the action.
32
+
33
+ ## Step Core Fields
34
+
35
+ Meaningful non-user steps should populate:
36
+
37
+ - `step`, `turn`, `actor`, `action`
38
+ - `operation`, `tool`
39
+ - `observation`, `input`, `output`, `state_change`
40
+ - `reasoning`
41
+ - `caused_by`, `causal_type`, `causal_note`
42
+ - `success`, `step_outcome`
43
+ - `artifact_refs` when evidence or outputs are created, read, or validated
44
+
45
+ ## Conditional Fields
46
+
47
+ Populate conditional fields when the event calls for them:
48
+
49
+ - `input_source` when input comes from the user, a prior step, a tool result, an artifact, mentor feedback, verifier feedback, expert feedback, a follow-up, or retry context.
50
+ - `feedback_type` and `feedback_content` when the step records feedback, correction, approval, clarification, revision guidance, or follow-up instructions.
51
+ - `retry_of` when a step repairs or revises a prior step.
52
+ - `alternatives_considered` for meaningful strategy, tool, remediation, or design choices.
53
+ - `execution_mode` defaults to `serial`; use `parallel` and `parallel_group` only for real fanout work.
54
+ - `started_at` and `ended_at` only when measured by runtime.
55
+
56
+ ## Environment Domain Taxonomy And Interaction Surface Taxonomy
57
+
58
+ Every meaningful operation should identify its direct interface with `interaction_surface`, broader category with `environment_domain`, and a subtype with `surface_type` when useful.
59
+
60
+ Supported surfaces:
61
+
62
+ - `api`
63
+ - `mcp_tool`, `mcp_resource`, `mcp_prompt`
64
+ - `browser`, `computer_use`
65
+ - `cli`, `file`, `codebase`
66
+ - `database`
67
+ - `spreadsheet`, `table`
68
+ - `search`
69
+ - `cloud_console`, `saas_app`
70
+ - `async_job`, `queue`, `webhook`, `scheduler`
71
+ - `messaging`, `email`, `collaboration`
72
+ - `document`, `pdf`
73
+ - `multimodal`
74
+ - `device`, `industrial`, `physical`
75
+ - `mixed`, `other_tool`, `other_surface`, `unknown`
76
+
77
+ If a workflow crosses systems, use `environment_domain = mixed`, record `connected_surfaces`, split actions by system, and preserve `cross_system_dependencies`, `handoff_refs`, `state_sync_refs`, `consistency_checks`, and `system_of_record`.
78
+
79
+ ## Surface-Specific Evidence
80
+
81
+ When an operation clearly uses a surface, do not leave the relevant fields silently empty. If data is unavailable, set `surface_capture_status`, `surface_capture_notes`, and `missing_surface_fields`.
82
+
83
+ API steps should capture endpoint, method, version, status, request/response refs, resource IDs, auth mode without secrets, pagination, rate limits, retries, and errors.
84
+
85
+ MCP steps should capture server, capability type, tool/resource/prompt name, argument refs, result refs, schemas, call IDs, and errors.
86
+
87
+ Database steps should capture database type, schema/table, query type, query ref or hash, row counts, affected rows, transaction IDs, snapshots, explain plans, rollback refs, and errors.
88
+
89
+ Spreadsheet and table steps should capture workbook refs, sheet names, ranges, row/column counts, formula refs, pivots, charts, validation refs, before/after refs, and diffs.
90
+
91
+ CLI, file, and codebase steps should capture command, cwd ref, exit code, stdout/stderr refs, file operations, paths, diffs, patches, git state, test/build/lint refs, process IDs, and timeouts.
92
+
93
+ Search steps should capture query, provider, scope, filters, result count, selected result refs, citation refs, ranking signals, time range, and errors.
94
+
95
+ Browser, computer-use, and software steps should capture UI surface, app name/version, OS, device, window/page title, URL or resource ID, visible-state refs, screenshot refs, DOM/accessibility refs, selectors, coordinates, action type, input text, before/after refs, network/API refs, and software state refs.
96
+
97
+ Cloud, SaaS, and enterprise app steps should capture service, workspace/project/tenant identifiers when safe, resource or ticket IDs, object state refs, permission context, region, environment, deployment IDs, audit logs, and change-request refs.
98
+
99
+ Async, queue, webhook, and scheduler steps should capture job/message/webhook/schedule IDs, trigger type, enqueue/start/completion times, retry count, delivery/polling/callback status, result refs, and dead-letter refs.
100
+
101
+ Messaging, email, and collaboration steps should capture platform, channel/thread/message IDs, sender/recipient roles, message refs, attachment refs, decisions, approval state, and follow-up requirements.
102
+
103
+ Document, PDF, report, and extraction steps should capture document refs, document type, page/section refs, text/OCR/table/figure/citation/annotation refs, summaries, and document diffs.
104
+
105
+ Device, industrial, and physical workflow steps should capture physical environment type, device details when safe, sensor/telemetry refs, actuator command summaries, control mode, before/after physical state refs, calibration refs, safety state, safety limits, operator override, human supervision, simulation or real-world status, latency, tolerance, rollback action, emergency stop, and compliance refs.
106
+
107
+ ## Multi-Agent And Multimodal Support
108
+
109
+ Multi-agent workflows should preserve `actor_kind`, `actor_role`, `agent_id`, `agent_name`, `subagent_id`, `subagent_name`, `subagent_role`, `parent_agent_id`, `delegation_id`, `delegation_source_step`, `handoff_reason`, `handoff_payload_ref`, `handoff_output_refs`, `subagent_output_refs`, `coordination_pattern`, `communication_channel`, and `depends_on_agent_outputs`.
110
+
111
+ Multimodal workflows should preserve `modality`, `modalities`, `media_type`, `mime_type`, `artifact_role`, `artifact_hash`, `artifact_preview_ref`, `ocr_text_ref`, `transcript_ref`, `annotation_ref`, `bbox_refs`, `frame_refs`, `timecode_refs`, `table_refs`, `sheet_refs`, and `derived_text_summary`.
112
+
113
+ ## Completeness Warnings
114
+
115
+ New traces should record warnings, not fabricate missing values:
116
+
117
+ - `surface_capture_status = complete | partial | unavailable | not_applicable`
118
+ - `surface_capture_notes`
119
+ - `missing_surface_fields`
120
+ - `trace_quality_warnings`
121
+
122
+ Old seed traces remain compatible when these fields are absent.
123
+
124
+ ## Loop Review Packets
125
+
126
+ Each new iterative workflow loop should create review artifacts after an Apprentice Agent iteration and before model or expert review. The package-level structure is:
127
+
128
+ ```text
129
+ loops/
130
+ loop_manifest.json
131
+ iterations/
132
+ 001/
133
+ review_packet.md
134
+ review_packet.json
135
+ output_snapshot.json
136
+ artifact_index.json
137
+ trace_refs.json
138
+ rubric_status.json
139
+ verifier_status.json
140
+ evaluator_feedback.json
141
+ reviewer_feedback.json
142
+ revision_plan.json
143
+ diff_report.json
144
+ loop_decision.json
145
+ ```
146
+
147
+ `review_packet.json` is the current iteration dossier. It should include `loop_id`, `loop_iteration`, mode, task/package/run ids, the current goal, output refs, `actual_outputs_ref`, artifact refs and previews, trace refs, key trace steps, rubric and verifier status, evaluator status, known failures, missing outputs, open questions, surface/environment summaries, previous iteration refs, diff from the previous iteration, reviewer instructions, recommended review focus, stop/continue options, and `created_at`.
148
+
149
+ Autonomous model review should use the review packet as the review source before judging the attempt. Expert-Led review should show or link the packet before collecting expert feedback. Review feedback records should say whether the reviewer was `mentor_model_provider`, `human_expert`, `org_custom_reviewer`, or `simulated_for_test`; simulated or auto-test checkpoints must not be presented as real human review.
150
+
151
+ Revision plans should cite feedback refs, list issues to fix, artifacts and outputs to update, verification steps, stop conditions, and creation time. The next iteration should record feedback refs used, changes made, changed artifacts/outputs, and whether feedback was applied. Record-only follow-ups may create a follow-up review update without inventing new execution data.
152
+
153
+ ## Experience Compiler Use
154
+
155
+ The Experience Compiler runs after completed task work and follow-ups. It derives reusable runtime learning and training-time data from package evidence: task packets, rubrics, traces, `actual_outputs.json`, artifacts, attempt manifests, evaluator feedback, grader results, verifier results, revision plans, process supervision, reward modeling, revision preference pairs, lessons, follow-up records, mentor checkpoints, loop review packets, reviewer feedback, loop decisions, and diff reports.
156
+
157
+ The compiler emits:
158
+
159
+ - Experience Pack material
160
+ - Skill Pack material, including `skill_pack/skill.md`
161
+ - Runtime Learning Package material
162
+ - Training-Time Package material
163
+ - eval, verifier, reward, and preference rows
164
+ - observed environment-response rows
165
+ - surface event rows
166
+ - `environment_spec.json`
167
+ - reports and transfer-readiness records
168
+
169
+ It does not claim model training happened. It produces training-ready and runtime-ready material grounded in observed workflow evidence.
170
+
171
+ ## World-Model-Ready Fields
172
+
173
+ World-model-ready fields include `environment_domain`, `interaction_surface`, `state_before`, `agent_action`, `observed_environment_response`, `state_after`, `turn_idx`, `total_turns`, and environment-response quality scores.
174
+
175
+ ## World-Model-Ready Observed Rows
176
+
177
+ Observed environment-response rows should include state/action/next-state style data:
178
+
179
+ - `environment_domain`
180
+ - `interaction_surface`
181
+ - `state_before`
182
+ - `agent_action`
183
+ - `observed_environment_response`
184
+ - `state_after`
185
+ - `turn_idx`, `total_turns`
186
+ - `format_score`, `factuality_score`, `consistency_score`, `realism_score`, `training_quality_score`, `environment_response_quality_score`
187
+
188
+ These rows are saved as `environment_response_pairs.jsonl` in Experience Compiler outputs. `environment_spec.json` describes replay and environment readiness. No simulated environment responses are part of the product flow. There is no Qwen-AgentWorld runtime or simulator config in the product flow, and traces must not emit `simulated_environment_response`.
189
+
190
+ ## Not Included
191
+
192
+ Do not add commerce metadata, public ranking language, or Apprentice Agent self-eval as outcome truth. Do not include secrets, API keys, auth headers, cookies, private local paths, `.env`, `.env.local`, source scrape internals, or huge binaries in JSON.
@@ -0,0 +1,61 @@
1
+ # Agent Apprenticeship v0.2.0 Technical Release Notes
2
+
3
+ Agent Apprenticeship v0.2.0 expands the Experience Compilation system from Runtime Training reuse into a fuller package for agent training, evaluation, replay, verifier/reward work, and provenance audit.
4
+
5
+ ## Core Product Changes
6
+
7
+ - Full Experience Compilation packages now include traces, attempts, artifacts, actual outputs, loop review packets, evaluation/verifier/grader records, Runtime Training, training-time packages, eval packages, environment/replay packages, manifests, and source evidence maps where available.
8
+ - Public Ecosystem mode defaults to automatic upload of the full Experience Compilation after completed tasks.
9
+ - Private Internal Only mode records a no-upload path and does not upload completed tasks.
10
+ - Ecosystem consumption is centered on two actions: Export Full Experience Compilation and Install Runtime Training.
11
+ - Runtime Training install/use records installed skill refs, selected Runtime Training refs, confidence metadata, injected sections, and compact contract-focused context.
12
+ - `apprentice bundle check` accepts local Experience Compilation folders that use task/package/compiler manifests, including regenerated seed task packages.
13
+
14
+ ## Experience Compiler And Training Packages
15
+
16
+ - Experience Compiler outputs now include stronger package metadata, schema versions, compiler versions, package versions from `get_package_version()`, row counts, public/private mode, and provenance fields.
17
+ - Generated package material is no longer treated as only prompt/completion data. The package supports SFT and LoRA-ready instruction rows, process supervision, reward model rows, verifier model rows, preference pairs, critique/revision pairs, failure cases, task variants, eval/rubric rows, environment/replay rows, and agentic rollout material.
18
+ - Source evidence maps now include stable evidence IDs, evidence types, visibility, confidence, content hashes where available, row evidence links, and validation for broken refs.
19
+ - Eval and environment packages now have first-class manifests and replay/scoring-oriented metadata.
20
+
21
+ ## Demo B Local Proof
22
+
23
+ Demo B is a local ALE workflow-family mirrored transfer proof, not an official ALE benchmark score.
24
+
25
+ - Completed workflow families: 7
26
+ - Improved: 7
27
+ - Same: 0
28
+ - Worse: 0
29
+ - Severe regressions: 0
30
+ - Average baseline score: 0.3429
31
+ - Average treatment score: 0.8929
32
+ - Average delta: +0.5500
33
+ - Median delta: +0.4500
34
+ - Leakage check: passed
35
+
36
+ The supported claim is that Agent Apprenticeship Runtime Training from source Experience Compilations improved related held-out mirrored workflow-family tasks in this local proof set.
37
+
38
+ ## Seed Dataset v0.2
39
+
40
+ Seed Dataset v0.2 is an Experience Compilation dataset generated from seed tasks. It is not the specialized bioactive/wellness model-training dataset.
41
+
42
+ - Full Experience Compilations: 505
43
+ - Skill packs: 505
44
+ - Runtime Training packages: 505
45
+ - Training-time packages: 505
46
+ - Eval packages: 505
47
+ - Environment/replay packages: 505
48
+ - Source evidence maps: 505
49
+ - Source evidence rows: 6,483
50
+ - Row evidence links: 15,004
51
+ - Viewer/export configs: 15
52
+ - Normalized Data Viewer rows: 39,835
53
+
54
+ Use the wording “505 Experience Compilations plus 39,835 normalized Data Viewer rows.” Do not describe the normalized viewer rows as tasks.
55
+
56
+ ## Release Boundary
57
+
58
+ - The package version is 0.2.0 for release-candidate builds.
59
+ - The regenerated Seed Dataset v0.2 was generated before npm v0.2.0 publication and records the local package metadata present at generation time.
60
+ - No model weights are included.
61
+ - No official ALE benchmark score is claimed for the mirrored transfer tasks.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-apprenticeship",
3
- "version": "0.1.8",
3
+ "version": "0.2.0",
4
4
  "description": "The living ecosystem for AI agents learning from real-world work through iterative loops and training-signal exchange.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -14,6 +14,7 @@
14
14
  "files": [
15
15
  "README.md",
16
16
  "LICENSE",
17
+ "docs",
17
18
  "pyproject.toml",
18
19
  "src/agent_apprenticeship_trace",
19
20
  "bin"
package/pyproject.toml CHANGED
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "agent-apprenticeship"
7
- version = "0.1.8"
7
+ version = "0.2.0"
8
8
  description = "Open framework for turning real agent work into transferable agent experience"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -1,2 +1,2 @@
1
1
  """Agent Apprenticeship framework."""
2
- __version__ = "0.1.8"
2
+ __version__ = "0.2.0"
@@ -3,6 +3,7 @@ from __future__ import annotations
3
3
  import shutil
4
4
  import tempfile
5
5
  import re
6
+ from datetime import datetime, timezone
6
7
  from pathlib import Path
7
8
  from typing import Any
8
9
 
@@ -12,6 +13,7 @@ from .public_sanitizer import sanitize_public_obj, sanitize_public_text
12
13
  from .release_exporter import create_release
13
14
  from .tdo import tdo_manifest_fields_from_report
14
15
  from .loop_review import summarize_loop_reviews
16
+ from .version import get_package_version
15
17
 
16
18
 
17
19
  def _count_jsonl(path: Path) -> int:
@@ -87,8 +89,12 @@ def _run_status(release_root: Path) -> str:
87
89
 
88
90
 
89
91
  def contribution_counts(release_root: Path) -> dict[str, int]:
92
+ trace_count = _count_jsonl(release_root / "agent_traces.jsonl")
93
+ actual_outputs_count = _count_jsonl(release_root / "actual_outputs.jsonl")
90
94
  return {
91
- "attempts": _count_jsonl(release_root / "actual_outputs.jsonl"),
95
+ "attempts": actual_outputs_count,
96
+ "actual_outputs_count": actual_outputs_count,
97
+ "trace_count": trace_count,
92
98
  "traced_steps": _trace_step_count(release_root / "agent_traces.jsonl"),
93
99
  "process_supervision_rows": _count_jsonl(release_root / "process_supervision.jsonl"),
94
100
  "reward_modeling_rows": _count_jsonl(release_root / "reward_modeling.jsonl"),
@@ -310,16 +316,31 @@ def _bundle_metadata_shape(bundle_root: Path, release_root: Path, settings: Sett
310
316
  role = task.get("agent_apprentice_role") or task.get("apprenticeship_role")
311
317
  metadata = {
312
318
  "bundle_id": f"aa-bundle-{_slug(run_id)}",
319
+ "experience_compilation_id": f"aa-compilation-{_slug(run_id)}",
320
+ "compilation_id": f"aa-compilation-{_slug(run_id)}",
321
+ "schema_version": "aa-experience-compilation-v0.2",
322
+ "package_version": get_package_version(),
323
+ "created_at": datetime.now(timezone.utc).isoformat().replace("+00:00", "Z"),
313
324
  "title": title,
325
+ "task_title": title,
314
326
  **counts,
315
327
  "domains": _list_value(task.get("domain")),
316
328
  "subdomains": _list_value(task.get("subdomain")),
329
+ "domain": (_list_value(task.get("domain")) or ["general"])[0],
330
+ "subdomain": (_list_value(task.get("subdomain")) or ["general"])[0],
331
+ "workflow_family": task.get("task_family") or task.get("workflow_family") or task.get("workflow_type") or "general_workflow",
332
+ "tags": sorted(set([str(task.get("domain") or "general"), str(task.get("subdomain") or "general"), str(task.get("workflow_type") or "workflow")]))[:12],
333
+ "surfaces": [],
334
+ "tools": [],
317
335
  "agent_apprentice_role": role,
318
336
  "expected_economic_value": task.get("expected_economic_value"),
319
337
  "expected_economic_value_for_agent_apprentice": task.get("expected_economic_value_for_agent_apprentice"),
320
338
  "apprenticeship_mode": _session_apprenticeship_mode(session, settings),
321
339
  "apprenticeship_mode_display": apprenticeship_mode_display(_session_apprenticeship_mode(session, settings)),
322
340
  "mentor_mode": _session_mentor_mode(session, settings),
341
+ "public_private_mode": getattr(settings, "contribution_mode", None),
342
+ "sharing_upload_mode": getattr(settings, "contribution_mode", None),
343
+ "private_internal_no_upload_confirmed": getattr(settings, "contribution_mode", None) == "private_internal",
323
344
  "task_status": task_status,
324
345
  "run_status": run_status,
325
346
  }
@@ -391,7 +412,14 @@ def _tdo_manifest_shape(release_root: Path) -> dict[str, Any]:
391
412
  def _experience_compiler_manifest_shape(release_root: Path, latest_report: dict[str, Any]) -> dict[str, Any]:
392
413
  compiler_dirs = sorted(path for path in (release_root / "packages").glob("*/experience_compiler") if path.is_dir())
393
414
  refs: list[str] = []
415
+ compiler_manifest: dict[str, Any] = {}
416
+ source_evidence_coverage: dict[str, Any] = {}
417
+ quality_report: dict[str, Any] = {}
394
418
  if len(compiler_dirs) == 1:
419
+ compiler_manifest = read_json(compiler_dirs[0] / "compiler_manifest.json") if (compiler_dirs[0] / "compiler_manifest.json").exists() else {}
420
+ source_map = read_json(compiler_dirs[0] / "source_evidence_map.json") if (compiler_dirs[0] / "source_evidence_map.json").exists() else {}
421
+ source_evidence_coverage = source_map.get("coverage_statistics") or {}
422
+ quality_report = read_json(compiler_dirs[0] / "quality_report.json") if (compiler_dirs[0] / "quality_report.json").exists() else {}
395
423
  for child in sorted(compiler_dirs[0].rglob("*")):
396
424
  if child.is_file():
397
425
  refs.append(f"experience_compiler/{child.relative_to(compiler_dirs[0]).as_posix()}")
@@ -406,10 +434,17 @@ def _experience_compiler_manifest_shape(release_root: Path, latest_report: dict[
406
434
  "experience_compiler_id": str(latest_report.get("tdo_id") or "").replace("tdo_", "compiler_", 1),
407
435
  "experience_compiler_output_refs": refs,
408
436
  "experience_compiler_rows_by_type": latest_report.get("rows_accepted_by_type") or {},
437
+ "training_row_counts": latest_report.get("rows_accepted_by_type") or {},
438
+ "training_row_counts_by_file": compiler_manifest.get("training_row_counts_by_file") or quality_report.get("training_row_counts_by_file") or {},
439
+ "source_evidence_map_count": source_evidence_coverage.get("evidence_ref_count"),
440
+ "source_evidence_row_link_count": source_evidence_coverage.get("row_link_count"),
409
441
  "experience_compiler_rounds_run": latest_report.get("rounds_run"),
410
442
  "experience_compiler_average_quality_score": latest_report.get("average_quality_score"),
411
443
  "experience_compiler_average_reuse_value_score": latest_report.get("average_reuse_value_score"),
412
444
  "experience_compiler_judge_source": latest_report.get("tdo_judge_source"),
445
+ "compiler_version": compiler_manifest.get("compiler_version"),
446
+ "training_row_schema_version": compiler_manifest.get("training_row_schema_version"),
447
+ "source_evidence_map_schema_version": compiler_manifest.get("source_evidence_map_schema_version"),
413
448
  }
414
449
 
415
450
 
@@ -152,6 +152,12 @@ def _print_public_ecosystem_contribution_help(bundle: str | Path) -> None:
152
152
  typer.echo('Forsy ecosystem')
153
153
 
154
154
 
155
+ def _print_private_internal_share_note(bundle: str | Path) -> None:
156
+ typer.echo('Private Internal Only: no Public Ecosystem upload was made.')
157
+ typer.echo('Optional manual share:')
158
+ typer.echo(f'apprentice ecosystem contribute {bundle}')
159
+
160
+
155
161
  def _print_first_run_banner() -> None:
156
162
  typer.echo(FIRST_RUN_BANNER)
157
163
  typer.echo("")
@@ -199,7 +205,7 @@ def _print_task_result(
199
205
  mode = get_settings().training_contribution_mode
200
206
  typer.echo(f'Agent Training Contribution Mode: {training_contribution_mode_display(mode)}')
201
207
  if mode == "private_internal_only":
202
- _print_public_ecosystem_contribution_help(bundle)
208
+ _print_private_internal_share_note(bundle)
203
209
  typer.echo('')
204
210
  typer.echo('View files:')
205
211
  typer.echo(f'open {bundle}')
@@ -226,7 +232,7 @@ def _print_session_finished(status: dict, *, include_contribution_help: bool=Tru
226
232
  mode = get_settings().training_contribution_mode
227
233
  typer.echo(f'Agent Training Contribution Mode: {training_contribution_mode_display(mode)}')
228
234
  if mode == "private_internal_only":
229
- _print_public_ecosystem_contribution_help(status.get('contribution_bundle_path'))
235
+ _print_private_internal_share_note(status.get('contribution_bundle_path'))
230
236
  typer.echo('')
231
237
  typer.echo('View files:')
232
238
  typer.echo(f"open {status.get('contribution_bundle_path')}")
@@ -1439,6 +1445,8 @@ def start(
1439
1445
  status = read_run_status(run_root)
1440
1446
  if quiet:
1441
1447
  _print_task_result(status, include_contribution_help=False)
1448
+ elif not json_progress:
1449
+ _print_task_result(status)
1442
1450
  _handle_ecosystem_auto_share(status, quiet=quiet, json_progress=json_progress)
1443
1451
 
1444
1452
  @app.command('run')
@@ -1652,7 +1660,7 @@ def status(run_id: str=typer.Argument(..., help='Run id or path to inspect.')):
1652
1660
  typer.echo(format_run_status(read_run_status(run_root)))
1653
1661
 
1654
1662
 
1655
- @app.command('watch')
1663
+ @app.command('watch', help='Watch live run progress, loop reviews, artifacts, and Experience Compiler status.')
1656
1664
  def watch(
1657
1665
  run_id: str=typer.Argument(..., help='Run id or path to watch.'),
1658
1666
  interval: float=typer.Option(1.0, '--interval', help='Polling interval in seconds.'),
@@ -3940,17 +3948,25 @@ def bundle_check(path: Path=typer.Argument(..., help='Experience Compilation fol
3940
3948
 
3941
3949
  issues: list[str] = []
3942
3950
  bundle = Path(path).expanduser()
3943
- manifest_path = bundle / "contribution_manifest.json"
3951
+ manifest_candidates = [
3952
+ bundle / "contribution_manifest.json",
3953
+ bundle / "task_manifest.json",
3954
+ bundle / "package_manifest.json",
3955
+ bundle / "manifest.json",
3956
+ bundle / "experience_compiler" / "compiler_manifest.json",
3957
+ ]
3958
+ manifest_path = next((candidate for candidate in manifest_candidates if candidate.exists()), manifest_candidates[0])
3944
3959
  if not bundle.exists():
3945
3960
  issues.append(f"Bundle path does not exist: {bundle}")
3946
3961
  elif not manifest_path.exists():
3947
- issues.append(f"Experience Compilation manifest not found: {manifest_path}")
3962
+ candidate_names = ", ".join(str(candidate.relative_to(bundle)) for candidate in manifest_candidates)
3963
+ issues.append(f"Experience Compilation manifest not found. Checked: {candidate_names}")
3948
3964
  manifest_data = {}
3949
3965
  if manifest_path.exists():
3950
3966
  try:
3951
3967
  manifest_data = read_json(manifest_path)
3952
3968
  except Exception as exc:
3953
- issues.append(f"contribution_manifest.json could not be parsed: {exc}")
3969
+ issues.append(f"{manifest_path.relative_to(bundle)} could not be parsed: {exc}")
3954
3970
  artifact_index_path = bundle / "outputs" / "artifacts_index.json"
3955
3971
  artifacts: list[dict] = []
3956
3972
  if artifact_index_path.exists():
@@ -4012,6 +4028,56 @@ def bundle_check(path: Path=typer.Argument(..., help='Experience Compilation fol
4012
4028
  read_json(file_path)
4013
4029
  except Exception as exc:
4014
4030
  issues.append(f"{file_path.relative_to(bundle)} could not be parsed: {exc}")
4031
+ source_map_path = compiler_dir / "source_evidence_map.json"
4032
+ if source_map_path.exists():
4033
+ try:
4034
+ source_map = read_json(source_map_path)
4035
+ evidence_ids = {
4036
+ str(item.get("evidence_id"))
4037
+ for item in source_map.get("evidence_catalog") or []
4038
+ if isinstance(item, dict) and item.get("evidence_id")
4039
+ }
4040
+ for link in source_map.get("row_evidence_links") or []:
4041
+ if not isinstance(link, dict):
4042
+ continue
4043
+ link_ids = link.get("evidence_ref_ids") or link.get("source_evidence_ids") or []
4044
+ for evidence_id in link_ids:
4045
+ if str(evidence_id) not in evidence_ids:
4046
+ issues.append(f"source_evidence_map row {link.get('row_id')} references unknown evidence id: {evidence_id}")
4047
+ orphan_count = (
4048
+ (source_map.get("coverage_statistics") or {}).get("orphan_evidence_id_count")
4049
+ if isinstance(source_map.get("coverage_statistics"), dict)
4050
+ else None
4051
+ )
4052
+ if orphan_count is None:
4053
+ orphan_count = (source_map.get("coverage") or {}).get("orphan_evidence_id_count")
4054
+ if orphan_count not in (None, 0):
4055
+ issues.append(f"source_evidence_map has orphan evidence ids: {orphan_count}")
4056
+ except Exception as exc:
4057
+ issues.append(f"{source_map_path.relative_to(bundle)} could not be validated: {exc}")
4058
+ seen_training_ids: set[str] = set()
4059
+ for file_path in compiler_dir.rglob("*.jsonl"):
4060
+ try:
4061
+ rows = read_jsonl(file_path)
4062
+ except Exception as exc:
4063
+ issues.append(f"{file_path.relative_to(bundle)} could not be parsed: {exc}")
4064
+ continue
4065
+ if "training_time_package" in file_path.parts or "eval_package" in file_path.parts or "loop_learning" in file_path.parts:
4066
+ for row in rows:
4067
+ if not isinstance(row, dict):
4068
+ continue
4069
+ row_id = row.get("row_id") or row.get("pair_id")
4070
+ if row_id:
4071
+ key = f"{file_path.relative_to(compiler_dir)}:{row_id}"
4072
+ if key in seen_training_ids:
4073
+ issues.append(f"Duplicate generated row id: {row_id}")
4074
+ seen_training_ids.add(key)
4075
+ if row.get("data_type") and not (
4076
+ row.get("source_evidence_ref_ids")
4077
+ or row.get("source_evidence_ids")
4078
+ or row.get("evidence_refs")
4079
+ ):
4080
+ issues.append(f"{file_path.relative_to(bundle)} row lacks evidence refs: {row_id or row.get('data_type')}")
4015
4081
  loops_dir = bundle / "loops"
4016
4082
  if loops_dir.exists():
4017
4083
  for file_path in loops_dir.rglob("*.json"):
@@ -4024,11 +4090,6 @@ def bundle_check(path: Path=typer.Argument(..., help='Experience Compilation fol
4024
4090
  read_jsonl(file_path)
4025
4091
  except Exception as exc:
4026
4092
  issues.append(f"{file_path.relative_to(bundle)} could not be parsed: {exc}")
4027
- for file_path in compiler_dir.rglob("*.jsonl"):
4028
- try:
4029
- read_jsonl(file_path)
4030
- except Exception as exc:
4031
- issues.append(f"{file_path.relative_to(bundle)} could not be parsed: {exc}")
4032
4093
  surface_warnings: list[str] = []
4033
4094
  for trace_path in [bundle / "traces" / "agent_traces.jsonl", bundle / "traces" / "raw_agent_traces.jsonl"]:
4034
4095
  if not trace_path.exists():
@@ -4061,7 +4122,7 @@ def bundle_check(path: Path=typer.Argument(..., help='Experience Compilation fol
4061
4122
  typer.echo(f"Task status: {status}")
4062
4123
  for warning in surface_warnings[:10]:
4063
4124
  typer.echo(f"Surface completeness warning: {redact_secrets(warning)}")
4064
- typer.echo("This Experience Compilation is ready to add to the public ecosystem.")
4125
+ typer.echo("This Experience Compilation is ready for local export, Runtime Training install, or explicit sharing.")
4065
4126
 
4066
4127
 
4067
4128
  @bundle_app.command('contribute')