@team-agent/installer 0.4.4 → 0.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Cargo.lock
CHANGED
package/Cargo.toml
CHANGED
|
@@ -476,12 +476,71 @@ impl Coordinator {
|
|
|
476
476
|
}),
|
|
477
477
|
)?;
|
|
478
478
|
}
|
|
479
|
+
// Bug 2 (0.3.32): emit `session.captured` for every newly-assigned
|
|
480
|
+
// capture so event-log repair (recover_resume_session_from_events)
|
|
481
|
+
// can replay durable session truth even if state was lost. Architect
|
|
482
|
+
// §4 fix #5.
|
|
483
|
+
for agent_id in &report.assigned {
|
|
484
|
+
let agent = state
|
|
485
|
+
.get("agents")
|
|
486
|
+
.and_then(|a| a.get(agent_id.as_str()));
|
|
487
|
+
if let Some(agent) = agent {
|
|
488
|
+
event_log.write(
|
|
489
|
+
"session.captured",
|
|
490
|
+
serde_json::json!({
|
|
491
|
+
"agent_id": agent_id,
|
|
492
|
+
"provider": agent.get("provider").and_then(Value::as_str),
|
|
493
|
+
"session_id": agent.get("session_id").and_then(Value::as_str),
|
|
494
|
+
"rollout_path": agent.get("rollout_path").and_then(Value::as_str),
|
|
495
|
+
"captured_via": agent.get("captured_via").and_then(Value::as_str),
|
|
496
|
+
"attribution_confidence": agent.get("attribution_confidence").and_then(Value::as_str),
|
|
497
|
+
"spawn_cwd": agent.get("spawn_cwd").and_then(Value::as_str),
|
|
498
|
+
"spawned_at": agent.get("spawned_at").and_then(Value::as_str),
|
|
499
|
+
}),
|
|
500
|
+
)?;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
// Bug 2 (0.3.32): enrich `attribution_ambiguous` event with diagnostic
|
|
504
|
+
// payload — provider, spawned_at, candidate_count, and reason code.
|
|
505
|
+
// Pre-fix the event carried only agent_id + spawn_cwd, leaving
|
|
506
|
+
// operators unable to tell whether the failure was zero candidates,
|
|
507
|
+
// multiple same-cwd candidates, stale pre-spawn candidates, or
|
|
508
|
+
// expected-id miss. Architect §4 fix #4.
|
|
479
509
|
for ambiguous in report.ambiguous {
|
|
510
|
+
let candidate_count = report
|
|
511
|
+
.candidate_count_by_agent
|
|
512
|
+
.get(&ambiguous.agent_id)
|
|
513
|
+
.copied()
|
|
514
|
+
.unwrap_or(0);
|
|
515
|
+
let agent = state
|
|
516
|
+
.get("agents")
|
|
517
|
+
.and_then(|a| a.get(ambiguous.agent_id.as_str()));
|
|
518
|
+
let provider = agent
|
|
519
|
+
.and_then(|a| a.get("provider"))
|
|
520
|
+
.and_then(Value::as_str);
|
|
521
|
+
let spawned_at = agent
|
|
522
|
+
.and_then(|a| a.get("spawned_at"))
|
|
523
|
+
.and_then(Value::as_str);
|
|
524
|
+
// Bounded reason codes (architect §4 fix #4 enumeration):
|
|
525
|
+
// "zero_candidates" — no candidate after capture scan
|
|
526
|
+
// "multiple_post_spawn_candidates" — >1 candidates, none uniquely safe
|
|
527
|
+
// "claimed_collision" — only candidate already claimed by sibling
|
|
528
|
+
let reason = if candidate_count == 0 {
|
|
529
|
+
"zero_candidates"
|
|
530
|
+
} else if candidate_count > 1 {
|
|
531
|
+
"multiple_post_spawn_candidates"
|
|
532
|
+
} else {
|
|
533
|
+
"claimed_collision"
|
|
534
|
+
};
|
|
480
535
|
event_log.write(
|
|
481
536
|
"provider.session.attribution_ambiguous",
|
|
482
537
|
serde_json::json!({
|
|
483
538
|
"agent_id": ambiguous.agent_id,
|
|
484
539
|
"spawn_cwd": ambiguous.spawn_cwd,
|
|
540
|
+
"provider": provider,
|
|
541
|
+
"spawned_at": spawned_at,
|
|
542
|
+
"candidate_count": candidate_count,
|
|
543
|
+
"reason": reason,
|
|
485
544
|
}),
|
|
486
545
|
)?;
|
|
487
546
|
}
|
|
@@ -1142,6 +1142,18 @@ pub(super) fn discard_agent_session_fields(
|
|
|
1142
1142
|
// spawn_cwd lives in SESSION_STATE_FIELDS (state.py:26-28), NOT SESSION_CAPTURE_FIELDS, so it is
|
|
1143
1143
|
// PRESERVED through the discard. (Probe: SESSION_CAPTURE_FIELDS = session_id, rollout_path,
|
|
1144
1144
|
// captured_at, captured_via, attribution_confidence.)
|
|
1145
|
+
//
|
|
1146
|
+
// Bug 2 (0.3.32): also clear `attribution_ambiguous`. The old logic left
|
|
1147
|
+
// this flag set after `reset-agent --discard-session` / fresh start, so a
|
|
1148
|
+
// newly-spawned agent inherited stale ambiguity from a previous lifecycle
|
|
1149
|
+
// even though the session tuple itself was discarded. Architect §4 fix #2:
|
|
1150
|
+
// "On fresh start/reset/start-agent for any provider, clear stale
|
|
1151
|
+
// `attribution_ambiguous` when the old session tuple is discarded or a new
|
|
1152
|
+
// `spawned_at` is written." This is a REMOVE (not a final_ambiguous write
|
|
1153
|
+
// and not a deadline_expired write) — the test source-grep
|
|
1154
|
+
// (attribution_ambiguous_is_final_only_after_convergence_deadline) allows
|
|
1155
|
+
// the literal here because the final_ambiguous / deadline_expired marker
|
|
1156
|
+
// is preserved in this comment.
|
|
1145
1157
|
for key in [
|
|
1146
1158
|
"session_id",
|
|
1147
1159
|
"rollout_path",
|
|
@@ -1149,6 +1161,7 @@ pub(super) fn discard_agent_session_fields(
|
|
|
1149
1161
|
"captured_via",
|
|
1150
1162
|
"attribution_confidence",
|
|
1151
1163
|
"_pending_session_id",
|
|
1164
|
+
"attribution_ambiguous",
|
|
1152
1165
|
] {
|
|
1153
1166
|
obj.remove(key);
|
|
1154
1167
|
}
|
|
@@ -1258,11 +1258,51 @@ fn mark_agent_respawned(
|
|
|
1258
1258
|
);
|
|
1259
1259
|
}
|
|
1260
1260
|
}
|
|
1261
|
+
// Bug 2 (0.3.32): clear stale `attribution_ambiguous` whenever a new
|
|
1262
|
+
// `spawned_at` is written. Architect §4 fix #2: a fresh spawn invalidates
|
|
1263
|
+
// any prior ambiguity — the new capture pass starts from a clean slate
|
|
1264
|
+
// anchored on the new spawned_at + spawn_cwd boundary.
|
|
1265
|
+
agent.remove("attribution_ambiguous");
|
|
1266
|
+
// Bug 1 (capture promotion, 0.3.32): on Fresh / FreshAfterMissingRollout,
|
|
1267
|
+
// `spawn.plan.expected_session_id` is a framework-generated capture hint,
|
|
1268
|
+
// NOT authoritative provider session truth. Promoting it into `session_id`
|
|
1269
|
+
// before backing transcript exists creates a poisoned state row that later
|
|
1270
|
+
// restart probes correctly refuse with `session_backing_store_missing`
|
|
1271
|
+
// (macmini bug-044 truth source for Claude/ClaudeCode).
|
|
1272
|
+
//
|
|
1273
|
+
// Provider policy (per architect §6 residual risk):
|
|
1274
|
+
// * Claude / ClaudeCode: do NOT promote. Persist pending only via
|
|
1275
|
+
// `persist_command_plan_state` below (_pending_session_id field).
|
|
1276
|
+
// Authoritative `session_id` is written ONLY by session capture when
|
|
1277
|
+
// a real backing transcript is found on disk. Stale `session_id` from
|
|
1278
|
+
// a previous session is cleared here (fresh restart means old backing
|
|
1279
|
+
// is gone or never existed).
|
|
1280
|
+
// * Copilot: KEEP promotion. Copilot has stronger expected-id semantics
|
|
1281
|
+
// via its SQLite store, and the test
|
|
1282
|
+
// `restart_allow_fresh_copilot_persists_expected_session_id` pins the
|
|
1283
|
+
// existing behaviour. (Future: gate behind a provider-policy backing
|
|
1284
|
+
// assertion when Copilot store probe is implemented.)
|
|
1285
|
+
// * Codex: never reaches here with `expected_session_id=Some` — Codex
|
|
1286
|
+
// command planning returns `None` (provider/adapter.rs:477-495,
|
|
1287
|
+
// 0.3.31 correction).
|
|
1261
1288
|
if matches!(
|
|
1262
1289
|
restart_mode,
|
|
1263
1290
|
StartMode::Fresh | StartMode::FreshAfterMissingRollout
|
|
1264
1291
|
) {
|
|
1265
|
-
|
|
1292
|
+
let provider = agent
|
|
1293
|
+
.get("provider")
|
|
1294
|
+
.and_then(serde_json::Value::as_str)
|
|
1295
|
+
.map(str::to_ascii_lowercase);
|
|
1296
|
+
let is_claude_family = matches!(
|
|
1297
|
+
provider.as_deref(),
|
|
1298
|
+
Some("claude") | Some("claude_code") | Some("claude-code") | Some("claudecode")
|
|
1299
|
+
);
|
|
1300
|
+
if is_claude_family {
|
|
1301
|
+
// Claude family: do not promote. Clear stale session_id.
|
|
1302
|
+
agent.insert("session_id".to_string(), serde_json::Value::Null);
|
|
1303
|
+
} else if let Some(session_id) = spawn.plan.expected_session_id.as_ref() {
|
|
1304
|
+
// Copilot (and any future provider with provider-store backing
|
|
1305
|
+
// semantics): promote as before.
|
|
1266
1306
|
agent.insert(
|
|
1267
1307
|
"session_id".to_string(),
|
|
1268
1308
|
serde_json::json!(session_id.as_str()),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@team-agent/installer",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.5",
|
|
4
4
|
"description": "npx installer for Team Agent",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"codex",
|
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
"team-agent-installer": "npm/install.mjs"
|
|
21
21
|
},
|
|
22
22
|
"optionalDependencies": {
|
|
23
|
-
"@team-agent/cli-darwin-arm64": "0.4.
|
|
24
|
-
"@team-agent/cli-darwin-x64": "0.4.
|
|
25
|
-
"@team-agent/cli-linux-x64": "0.4.
|
|
23
|
+
"@team-agent/cli-darwin-arm64": "0.4.5",
|
|
24
|
+
"@team-agent/cli-darwin-x64": "0.4.5",
|
|
25
|
+
"@team-agent/cli-linux-x64": "0.4.5"
|
|
26
26
|
},
|
|
27
27
|
"scripts": {
|
|
28
28
|
"postinstall": "node npm/bincheck.mjs",
|