Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions .progress/001_20260611_134500_de-worker-b7-b9.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# DE worker B7-B9 (crates/paw-codex-worker only)

Branch: codex/de-vision-completion-20260611 (origin = GitHub nerdsane/temperpaw, PR #393 — do not edit PR, do not merge).
Baseline: 97 tests green (`cargo test -p paw-codex-worker`).

## What we are addressing
The temper kernel (ADR-0041) parses `X-Temper-Observe-Metadata` into `temper.observation.*`
span attributes, but the temperpaw worker sends nothing — DE telemetry cannot be joined to
episodes/variants/trials. Join fields live only in raw CorrelationJson. Simulated-user and
evaluator Codex runs hit confusing in-run 401s when runtime credentials are missing.

## Expected end state
1. Every worker→Temper call made on behalf of a DE work item carries the observe-metadata
header (producer.work_item_id, producer.worker_run_id, de.role, de.* join fields).
2. Observer runtime probes carry it too.
3. DE Codex children get TEMPER_OBSERVE_METADATA + DD_TAGS env vars mechanically.
4. Datadog context + prompt header expose the full resolved join-field set from one parser.
5. Missing runtime credentials and role/target mismatches fail the work item up-front with a
structured reason through the existing FailWorkerRun/receipt/FailWorkItem path.

## Plan (red-green per phase, one commit each)
1. B7a: new `directed_evolution/observe_metadata.rs` — `DirectedEvolutionJoinFields` parser
(one place, shared by B7+B8), header-value builder with kernel limits (32 keys, key<=96B,
value<=1024B), DD_TAGS builder, codex child env builder. Tests first (red), then impl.
2. B7b: thread `observe_metadata: Option<&str>` through `post_directed_evolution_action`,
`post_paw_orchestration_action`, DE `create_entity` calls; header inserted via
`headers_with_observe_metadata`. Observer probes (`observer_runtime_get_text`/collection
sample) take the header. Codex child env injection in `run_codex_exec_command` DE path.
3. B8: extend `directed_evolution_datadog_context` with resolved join fields; add resolved
join block to the DE prompt header. Tests assert full field set in both.
4. B9: runtime-auth preflight (correlation runtime_auth_env_vars + TEMPERPAW_RUNTIME_API_KEY/
TEMPER_API_KEY fallbacks; fail "runtime credential missing: none of [names] is set") for
simulated_user + codex evaluator roles when runtime_base_url present; role/target-type
assertions (simulated_user→Trial, evaluator→StageResult). Remove the now-redundant
StageResult bail in mechanical_evaluator.rs.
5. Full `cargo test -p paw-codex-worker`, push.

NOT in scope: B10 temper rev bump; genesis-side telemetry fail-closed/threshold logic (ADR-0018).

## Status
- [x] Baseline green (97)
- [x] Phase 1+2 (B7) — commit b56a1374, 113 tests green (16 new)
- [x] Phase 3 (B8) — commit 0a93201f, 117 tests green (4 new)
- [x] Phase 4 (B9) — commit 167b5143, 127 tests green (10 new)
- [x] Clippy clean (collapsed pre-existing nested if in boot recovery)
- [x] Full suite green (127, baseline 97) + pushed

## Deviations from plan
- B7a and B7b landed as one commit (b56a1374): committing the pure helpers
alone would have left dead-code warnings in the binary target.
- DirectedEvolutionJoinFields also carries runtime_base_url +
runtime_auth_env_vars (excluded from de.* entries) so B9's preflight
shares the same single CorrelationJson parse.
4 changes: 4 additions & 0 deletions crates/paw-codex-worker/fixtures/fake-codex.sh
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ case "$prompt" in
"PAW_CODEX_DOCTOR_EXEC_SMOKE:"*)
echo "PAW_CODEX_DOCTOR_EXEC_OK"
;;
"PAW_FAKE_CODEX_PRINT_OBSERVE_ENV:"*)
printf 'TEMPER_OBSERVE_METADATA=%s\n' "${TEMPER_OBSERVE_METADATA:-}"
printf 'DD_TAGS=%s\n' "${DD_TAGS:-}"
;;
"You are the independent reviewer"* | "You are the independent repo-health Patrol scan reviewer"*)
echo "SUMMARY: Fake reviewer approved the agent-led worker E2E output."
echo "LIVE_E2E: Confirmed the fake implementer marker exists in the assigned worktree."
Expand Down
18 changes: 14 additions & 4 deletions crates/paw-codex-worker/src/boot_watch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,19 +88,29 @@ async fn query_boot_entity_ids(
config: &Config,
entity_set: &str,
status: &str,
) -> Result<Vec<String>> {
query_boot_entity_ids_filtered(client, config, entity_set, &format!("Status eq '{status}'"))
.await
}

async fn query_boot_entity_ids_filtered(
client: &reqwest::Client,
config: &Config,
entity_set: &str,
filter: &str,
) -> Result<Vec<String>> {
let url = format!(
"{}/tdata/{}?$filter=Status eq '{}'&$orderby=Id desc&$top=50",
config.temper_url, entity_set, status
"{}/tdata/{}?$filter={}&$orderby=Id desc&$top=50",
config.temper_url, entity_set, filter
);
let response = client
.get(url)
.headers(headers(config)?)
.send()
.await
.with_context(|| format!("query {entity_set} with status {status} on boot"))?;
.with_context(|| format!("query {entity_set} with filter {filter} on boot"))?;
if !response.status().is_success() {
warn!(entity_set, status, http_status = %response.status(), "boot query failed");
warn!(entity_set, filter, http_status = %response.status(), "boot query failed");
return Ok(Vec::new());
}

Expand Down
1 change: 1 addition & 0 deletions crates/paw-codex-worker/src/codex_plan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ async fn run_codex_plan_mode(
workdir,
codex_plan_args(workdir, &prompt),
"run local codex plan mode",
&[],
)
.await?;
let stdout = String::from_utf8_lossy(&output.stdout);
Expand Down
Loading