fix(daemon)+test: accurate duplicate-ARRIVED message; broaden E90/E157 + names coverage
The duplicate-ARRIVED fix from the previous commit returned INVALID_OBJECT with the message "no substrate 'X'" — a lie, since the substrate exists. Rewrite ReportSubstrate so ARRIVED has its own ack mapping: a duplicate is CANNOT_DO_NOW with "substrate 'X' already exists" (a state conflict, not a missing object), and we never silently re-create over live FSM state. Coverage gaps closed: - C++: ARRIVED records carrier_id/slot (now asserted); module NOT_EXECUTING reset transition; duplicate-ARRIVED expects CANNOT_DO_NOW. - Interop: @eq.command now drives the real host S2F41 path (was @eq.on, so the headline decorator had zero wire coverage); @eq.command NameError on unknown name; eq.names var/alarm + dir() + typo-suggestion; replaced the two `check(..., True)` tautologies with full E90 journey + AT_DESTINATION and real error paths (ghost wafer raises, illegal module jump raises). All 8 daemon test cases (248 assertions) and 24 pyclient interop checks pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -533,13 +533,29 @@ class EquipmentService final : public pb::Equipment::Service {
|
||||
const std::string cid = req->carrier_id();
|
||||
const auto slot = static_cast<uint8_t>(req->slot());
|
||||
const auto m = req->milestone();
|
||||
auto outcome = rt_.read_sync([this, sid, cid, slot, m]() -> std::optional<bool> {
|
||||
auto& subs = rt_.model().substrates;
|
||||
if (m == pb::SubstrateReport::ARRIVED) {
|
||||
if (subs.create(sid, cid, slot) == gem::SubstrateStore::CreateResult::Denied_AlreadyExists)
|
||||
return std::nullopt; // → INVALID_OBJECT: duplicate substrate ID
|
||||
return true;
|
||||
|
||||
// ARRIVED creates the substrate. A duplicate is a real conflict (re-creating
|
||||
// would silently wipe the wafer's FSM state + history), so reject it with an
|
||||
// accurate message rather than the generic "no such object" path.
|
||||
if (m == pb::SubstrateReport::ARRIVED) {
|
||||
auto created = rt_.read_sync([this, sid, cid, slot]() {
|
||||
return rt_.model().substrates.create(sid, cid, slot) ==
|
||||
gem::SubstrateStore::CreateResult::Created;
|
||||
});
|
||||
if (!created) {
|
||||
resp->set_code(pb::Ack::CANNOT_DO_NOW);
|
||||
resp->set_message("engine io thread did not answer (not running?)");
|
||||
} else if (!*created) {
|
||||
resp->set_code(pb::Ack::CANNOT_DO_NOW);
|
||||
resp->set_message("substrate '" + sid + "' already exists");
|
||||
} else {
|
||||
resp->set_code(pb::Ack::ACCEPT);
|
||||
}
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
auto outcome = rt_.read_sync([this, sid, m]() -> std::optional<bool> {
|
||||
auto& subs = rt_.model().substrates;
|
||||
if (!subs.has(sid)) return std::nullopt;
|
||||
switch (m) {
|
||||
case pb::SubstrateReport::AT_WORK:
|
||||
|
||||
Reference in New Issue
Block a user