agent-apprenticeship 0.1.5 → 0.1.7

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.
Files changed (34) hide show
  1. package/README.md +0 -197
  2. package/bin/agent-apprenticeship.js +85 -37
  3. package/package.json +1 -1
  4. package/pyproject.toml +1 -1
  5. package/src/agent_apprenticeship_trace/__init__.py +1 -1
  6. package/src/agent_apprenticeship_trace/actual_outputs_normalizer.py +104 -28
  7. package/src/agent_apprenticeship_trace/apprentice_adapters.py +3 -1
  8. package/src/agent_apprenticeship_trace/artifact_resolver.py +6 -0
  9. package/src/agent_apprenticeship_trace/bundle_exporter.py +132 -2
  10. package/src/agent_apprenticeship_trace/cli.py +1229 -269
  11. package/src/agent_apprenticeship_trace/codex_runner.py +89 -6
  12. package/src/agent_apprenticeship_trace/config.py +251 -32
  13. package/src/agent_apprenticeship_trace/ecosystem_r2.py +515 -0
  14. package/src/agent_apprenticeship_trace/env.py +5 -5
  15. package/src/agent_apprenticeship_trace/evaluator.py +127 -11
  16. package/src/agent_apprenticeship_trace/grader.py +12 -11
  17. package/src/agent_apprenticeship_trace/learning.py +270 -1
  18. package/src/agent_apprenticeship_trace/llm_output_normalizer.py +8 -7
  19. package/src/agent_apprenticeship_trace/loop.py +103 -4
  20. package/src/agent_apprenticeship_trace/loop_review.py +686 -0
  21. package/src/agent_apprenticeship_trace/mentor_checkpoints.py +49 -21
  22. package/src/agent_apprenticeship_trace/openai_structured.py +84 -14
  23. package/src/agent_apprenticeship_trace/package_exporter.py +1 -1
  24. package/src/agent_apprenticeship_trace/progress.py +2 -1
  25. package/src/agent_apprenticeship_trace/public_run.py +369 -57
  26. package/src/agent_apprenticeship_trace/public_sanitizer.py +40 -3
  27. package/src/agent_apprenticeship_trace/rubric_generation.py +11 -10
  28. package/src/agent_apprenticeship_trace/schemas.py +378 -3
  29. package/src/agent_apprenticeship_trace/task_intake.py +43 -9
  30. package/src/agent_apprenticeship_trace/tdo.py +2304 -0
  31. package/src/agent_apprenticeship_trace/trace_normalizer.py +351 -17
  32. package/src/agent_apprenticeship_trace/trace_prompt.py +38 -11
  33. package/src/agent_apprenticeship_trace/training_signals.py +1 -1
  34. package/src/agent_apprenticeship_trace/verifier.py +12 -6
@@ -3,7 +3,7 @@ import json
3
3
  from pathlib import Path
4
4
  from pydantic import BaseModel
5
5
  from .schemas import RawTaskRecord, TaskIntakeSpec, TaskIntakeQualityReport
6
- from .config import get_settings
6
+ from .config import apprentice_agent_display_name, get_settings
7
7
  from .io import read_json, write_json
8
8
  from .openai_structured import extract_json_object, get_model_provider_status, run_structured_role
9
9
  from .public_sanitizer import sanitize_public_obj, sha256_text
@@ -12,7 +12,7 @@ class LLMTaskIntakeOutput(BaseModel):
12
12
  task_intake_spec: TaskIntakeSpec
13
13
  task_intake_quality_report: TaskIntakeQualityReport
14
14
 
15
- SOURCE_FIELD_KEYS={'source_url_or_ref','source_kind','source_url','source_ref','source_license'}
15
+ SOURCE_FIELD_KEYS={'source_url_or_ref','source_kind','source_url','source_ref','source_basis','source_license'}
16
16
 
17
17
  def _mentor_provider_can_attempt() -> bool:
18
18
  return bool(get_model_provider_status().get('provider_available'))
@@ -105,22 +105,55 @@ def apply_direct_task_sheet_metadata(spec: TaskIntakeSpec, raw: RawTaskRecord) -
105
105
  md['direct_task_sheet_fields_preserved']=bool(direct)
106
106
  return spec.model_copy(update={**updates, 'metadata_json': md})
107
107
 
108
+ def _apprentice_draft_metadata(raw: RawTaskRecord, expected: str) -> dict[str, object]:
109
+ settings = get_settings()
110
+ payload = raw.raw_payload or {}
111
+ constraints = payload.get('constraints') or []
112
+ output_requirements = payload.get('output_requirements') or []
113
+ environment_domain = payload.get('environment_domain') or payload.get('environment') or payload.get('domain') or 'unknown'
114
+ environment_type = payload.get('environment_type') or environment_domain or 'unknown'
115
+ role = payload.get('role') or payload.get('professional_role') or payload.get('apprenticeship_role') or raw.apprenticeship_role
116
+ return {
117
+ 'intake_source': 'apprentice_agent_draft',
118
+ 'draft_author': 'apprentice_agent',
119
+ 'apprentice_agent_id': settings.worker_agent,
120
+ 'apprentice_agent_name': apprentice_agent_display_name(settings),
121
+ 'mentor_audited': False,
122
+ 'mentor_audit_source': None,
123
+ 'audit_status': 'unaudited',
124
+ 'unaudited_reason': 'No Mentor Model or human audit was completed for this task-intake draft.',
125
+ 'role': role or 'Apprentice Agent',
126
+ 'expected_deliverables': [expected],
127
+ 'success_criteria': output_requirements or [f'Produce {expected}.'],
128
+ 'failure_modes': payload.get('failure_modes') or ['Missing required deliverable', 'Output does not satisfy the task instruction'],
129
+ 'expected_economic_value_rationale': payload.get('expected_economic_value_rationale') or 'Estimated from task domain, deliverable scope, and specialization signals.',
130
+ 'expected_economic_value_for_apprentice_agent_rationale': payload.get('expected_economic_value_for_agent_apprentice_rationale') or payload.get('expected_economic_value_for_apprentice_agent_rationale') or 'Estimated from the agent-executable portion of the workflow.',
131
+ 'environment_domain': environment_domain,
132
+ 'environment_type': environment_type,
133
+ 'training_use_cases': payload.get('training_use_cases') or ['task_following', 'artifact_generation', 'workflow_trace_learning'],
134
+ 'evaluation_use_cases': payload.get('evaluation_use_cases') or ['rubric_based_evaluation', 'artifact_contract_checking'],
135
+ 'verifier_use_cases': payload.get('verifier_use_cases') or ['artifact_presence_verification', 'evidence_grounding_verification'],
136
+ 'artifact_requirements': output_requirements or [expected],
137
+ 'trace_requirements': payload.get('trace_requirements') or ['record one meaningful action per step', 'reference generated artifacts', 'separate observation, input, output, and state_change'],
138
+ 'constraints': constraints,
139
+ }
140
+
108
141
  def deterministic_intake(raw: RawTaskRecord) -> tuple[TaskIntakeSpec, TaskIntakeQualityReport]:
109
142
  tid = raw.raw_task_id.replace('raw_','task_')
110
143
  direct=direct_task_sheet_metadata(raw)
111
144
  expected=raw.raw_payload.get('expected_deliverable') or raw.expected_deliverable or raw.raw_payload.get('expected_agent_deliverable','Completed deliverables and audit notes')
112
- spec=TaskIntakeSpec(task_id=tid, normalized_title=raw.raw_title, normalized_instruction=raw.raw_description, domain=direct.get('domain') or raw.raw_payload.get('domain','general'), subdomain=direct.get('subdomain') or raw.raw_payload.get('subdomain'), professional_role=raw.raw_payload.get('professional_role'), apprenticeship_role=direct.get('apprenticeship_role'), task_family=direct.get('task_family'), expected_economic_value=direct.get('expected_economic_value'), expected_economic_value_for_agent_apprentice=direct.get('expected_economic_value_for_agent_apprentice'), expected_pay=direct.get('expected_pay'), expected_apprentice_pay=direct.get('expected_apprentice_pay'), workflow_type=raw.raw_payload.get('workflow_type','analysis'), skill_targets=raw.raw_payload.get('skill_targets',['analysis','artifact_generation']), difficulty_tier=direct.get('difficulty_tier') or raw.raw_payload.get('difficulty_tier','medium'), expected_human_deliverable=raw.raw_payload.get('expected_human_deliverable', expected), expected_agent_deliverable=expected, input_requirements=raw.raw_payload.get('input_requirements',[]), output_requirements=raw.raw_payload.get('output_requirements',[]), required_context=raw.raw_payload.get('required_context',[]), assumptions=[], constraints=raw.raw_payload.get('constraints',[]), allowed_tools=['python','file_read','file_write','bash'], disallowed_tools=['browser'], privacy_classification=raw.raw_payload.get('privacy_classification','unknown'), license=None, allowed_use='local apprenticeship data generation', rubricability_score=0.8, verifiability_score=0.8, artifactability_score=0.9, needs_expert_review=bool(direct.get('needs_expert_review')) if direct.get('needs_expert_review') is not None else False, metadata_json={'runner':'deterministic','intake_source':'deterministic_fallback'})
145
+ spec=TaskIntakeSpec(task_id=tid, normalized_title=raw.raw_title, normalized_instruction=raw.raw_description, domain=direct.get('domain') or raw.raw_payload.get('domain','general'), subdomain=direct.get('subdomain') or raw.raw_payload.get('subdomain'), professional_role=raw.raw_payload.get('professional_role'), apprenticeship_role=direct.get('apprenticeship_role'), task_family=direct.get('task_family'), expected_economic_value=direct.get('expected_economic_value'), expected_economic_value_for_agent_apprentice=direct.get('expected_economic_value_for_agent_apprentice'), expected_pay=direct.get('expected_pay'), expected_apprentice_pay=direct.get('expected_apprentice_pay'), workflow_type=raw.raw_payload.get('workflow_type','analysis'), skill_targets=raw.raw_payload.get('skill_targets',['analysis','artifact_generation']), difficulty_tier=direct.get('difficulty_tier') or raw.raw_payload.get('difficulty_tier','medium'), expected_human_deliverable=raw.raw_payload.get('expected_human_deliverable', expected), expected_agent_deliverable=expected, input_requirements=raw.raw_payload.get('input_requirements',[]), output_requirements=raw.raw_payload.get('output_requirements',[]), required_context=raw.raw_payload.get('required_context',[]), assumptions=[], constraints=raw.raw_payload.get('constraints',[]), allowed_tools=['python','file_read','file_write','bash'], disallowed_tools=['browser'], privacy_classification=raw.raw_payload.get('privacy_classification','unknown'), license=None, allowed_use='local apprenticeship data generation', rubricability_score=0.8, verifiability_score=0.8, artifactability_score=0.9, needs_expert_review=bool(direct.get('needs_expert_review')) if direct.get('needs_expert_review') is not None else False, metadata_json=_apprentice_draft_metadata(raw, expected))
113
146
  spec=apply_direct_task_sheet_metadata(spec, raw)
114
147
  settings=get_settings()
115
148
  if settings.rubric_mode in {'hybrid','llm_default'} and _mentor_provider_can_attempt() and settings.llm_task_intake_enabled:
116
- spec.metadata_json.update({'llm_task_intake_enabled': True, 'llm_unavailable': True, 'intake_source':'deterministic_fallback', 'provider': _mentor_provider_id()})
117
- q=TaskIntakeQualityReport(task_id=tid, instruction_clarity_score=0.8, input_completeness_score=0.8, output_contract_score=0.9, rubricability_score=spec.rubricability_score, verifiability_score=spec.verifiability_score, artifactability_score=spec.artifactability_score, privacy_risk_score=0.1, license_risk_score=0.1, ambiguity_score=0.2, overall_intake_quality_score=0.82, quality_flags=[], blockers=[], recommended_fix=None, metadata_json={})
149
+ spec.metadata_json.update({'llm_task_intake_enabled': True, 'mentor_audit_status': 'not_completed', 'provider': _mentor_provider_id()})
150
+ q=TaskIntakeQualityReport(task_id=tid, instruction_clarity_score=0.8, input_completeness_score=0.8, output_contract_score=0.9, rubricability_score=spec.rubricability_score, verifiability_score=spec.verifiability_score, artifactability_score=spec.artifactability_score, privacy_risk_score=0.1, license_risk_score=0.1, ambiguity_score=0.2, overall_intake_quality_score=0.82, quality_flags=['mentor_audit_pending'], blockers=[], recommended_fix=None, metadata_json={'draft_author':'apprentice_agent','mentor_audited':False})
118
151
  return spec,q
119
152
 
120
153
  def _intake_prompt(raw: RawTaskRecord) -> str:
121
154
  return """Return only valid JSON. Do not include markdown. Do not add extra top-level fields; place extras under metadata_json.extra_model_fields.
122
155
  Required skeleton: {"task_intake_spec":{"task_id":"...","normalized_title":"...","normalized_instruction":"...","domain":"general","workflow_type":"artifact_generation","difficulty_tier":"medium","expected_human_deliverable":"...","expected_agent_deliverable":"...","input_requirements":[],"output_requirements":[],"required_context":[],"assumptions":[],"constraints":[],"allowed_tools":[],"disallowed_tools":[],"privacy_classification":"unknown","rubricability_score":0.7,"verifiability_score":0.7,"artifactability_score":0.7,"needs_expert_review":false,"metadata_json":{}},"task_intake_quality_report":{"task_id":"...","instruction_clarity_score":0.7,"input_completeness_score":0.7,"output_contract_score":0.7,"rubricability_score":0.7,"verifiability_score":0.7,"artifactability_score":0.7,"privacy_risk_score":0.2,"license_risk_score":0.2,"ambiguity_score":0.3,"overall_intake_quality_score":0.7,"quality_flags":[],"blockers":[],"metadata_json":{}}}.
123
- Create a publishable task intake spec for reusable agent work experience. Populate title, domain, subdomain, agent apprenticeship role, expected_economic_value, and expected_economic_value_for_agent_apprentice when inferable from the task. Include task_family_guess, task_type, required_artifacts, hidden_reference_policy, risk_notes, subjectivity_level, evaluation_difficulty, and suggested_evaluator_type under metadata_json when not schema fields.
156
+ Audit and improve an Apprentice Agent-generated task intake draft for reusable agent work experience. Keep the Apprentice Agent as the draft author; your role is Mentor audit/improvement. Populate title, domain, subdomain, agent apprenticeship role, expected_economic_value, expected_economic_value_for_apprentice_agent, expected_economic_value rationale, environment_domain, environment_type, training_use_cases, evaluation_use_cases, verifier_use_cases, artifact_requirements, required_artifacts, trace_requirements, success_criteria, and failure_modes when inferable from the task. Put fields that are not first-class schema fields under metadata_json. Do not include commerce metadata, source URL fields, or agent self-evaluation claims.
124
157
  Raw task JSON:
125
158
  """ + json.dumps(_task_record_for_intake(raw), sort_keys=True)
126
159
 
@@ -139,8 +172,9 @@ def task_intake(raw: RawTaskRecord, role_root: Path | None=None) -> tuple[TaskIn
139
172
  spec=TaskIntakeSpec.model_validate(parsed['task_intake_spec'])
140
173
  spec=apply_direct_task_sheet_metadata(spec, raw)
141
174
  q=TaskIntakeQualityReport.model_validate(parsed['task_intake_quality_report'])
142
- spec.metadata_json.update({'intake_source':'llm','provider':rr.provider,'model':rr.model,'llm_prompt_ref_internal':str(role_root/'intake_agent/prompt.md'),'llm_response_ref_internal':str(role_root/'intake_agent/raw_output.txt'),'prompt_template_id':'task_intake_agent_v0','prompt_template_version':'0.1','prompt_hash':sha256_text(prompt),'public_response_summary':'Model-assisted task intake generated structured task spec.'})
143
- q.metadata_json.update({'intake_source':'llm','role_result_ref_internal':str(role_root/'intake_agent/role_result.json')})
175
+ draft_md = _apprentice_draft_metadata(raw, spec.expected_agent_deliverable)
176
+ spec.metadata_json.update({**draft_md,'intake_source':'apprentice_agent_draft','draft_author':'apprentice_agent','mentor_audited':True,'mentor_audit_source':'mentor_model','audit_status':'mentor_audited','provider':rr.provider,'model':rr.model,'llm_prompt_ref_internal':str(role_root/'intake_agent/prompt.md'),'llm_response_ref_internal':str(role_root/'intake_agent/raw_output.txt'),'prompt_template_id':'task_intake_agent_v0','prompt_template_version':'0.1','prompt_hash':sha256_text(prompt),'public_response_summary':'Mentor Model audited and improved an Apprentice-generated task intake draft.'})
177
+ q.metadata_json.update({'draft_author':'apprentice_agent','mentor_audited':True,'mentor_audit_source':'mentor_model','role_result_ref_internal':str(role_root/'intake_agent/role_result.json')})
144
178
  spec, q = _sanitize_spec_and_quality(spec, q)
145
179
  return spec,q
146
180
  if settings.rubric_mode == 'llm_required' or settings.llm_fail_closed:
@@ -150,6 +184,6 @@ def task_intake(raw: RawTaskRecord, role_root: Path | None=None) -> tuple[TaskIn
150
184
  raise
151
185
  spec,q=deterministic_intake(raw)
152
186
  if settings.llm_task_intake_enabled and _mentor_provider_can_attempt():
153
- spec.metadata_json.update({'intake_source':'deterministic_fallback','llm_unavailable':True,'provider':_mentor_provider_id()})
187
+ spec.metadata_json.update({'mentor_audit_status':'not_completed','provider':_mentor_provider_id()})
154
188
  spec, q = _sanitize_spec_and_quality(spec, q)
155
189
  return spec,q