Skip to content
Merged
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
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

## Unreleased

### Fixes

- Made repeated spec-intake discovery durably idempotent for implementation-
detail facts, so answering several product questions and approving a large
intake no longer re-appends the same facts until the mission bound is hit.
Oversized fact assessments are now rejected before any records or events
are written, preventing a partial facts file from advancing beyond mission
state.

### Production Qualification, Historical Fault Replay & Release Freeze — vNext.10.2 Phase 10

- Added a frozen production candidate identity bound to the exact commit,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@
"bytes": 155994
},
"cli.cjs": {
"sha256": "771fd77ef1f3dd42dc91c9bea8bb4fb3672d0edca40dac575646b6d044f8512c",
"bytes": 5858156
"sha256": "db1ed5fb7eacf11662e1206e27b74004cb31f1df88c4ee30b65ce092eb78e377",
"bytes": 5858878
},
"mcp-server.cjs": {
"sha256": "c3ee7b32ff982f9797ea7091aad9f12a0c95e30915cda98c01317219f9146f4c",
"bytes": 3777035
"sha256": "090a7686c19a94495baa75b230899f15a8e0b6036cfb09f73d4482686b621a3e",
"bytes": 3777757
}
}
}
37 changes: 27 additions & 10 deletions integrations/claude-code-plugin/specbridge/dist/cli.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -55236,6 +55236,13 @@ function recordAssessment(deps4, missionId, input) {
let mission = requireMissionState(deps4.workspace, missionId);
assertDiscoveryOpen(mission, "a discovery assessment");
const at = now(deps4).toISOString();
const incomingFacts = input.facts?.length ?? 0;
if (mission.counters.facts + incomingFacts > MISSION_LIMITS.maxFacts) {
throw new MissionError(
"SBM006",
`Recording ${incomingFacts} fact(s) would exceed the mission's ${MISSION_LIMITS.maxFacts}-fact bound (${mission.counters.facts} already recorded).`
);
}
const factIds = [];
const questionIds = [];
const decisionIds = [];
Expand Down Expand Up @@ -113848,6 +113855,7 @@ function emptyProjectionMap() {
return {
itemContracts: {},
itemDecisions: {},
itemFacts: {},
surfaceContracts: {},
topicDecisions: {}
};
Expand All @@ -113866,6 +113874,7 @@ function readProjectionMap(workspace, intakeId) {
return {
itemContracts: raw.itemContracts ?? {},
itemDecisions: raw.itemDecisions ?? {},
itemFacts: raw.itemFacts ?? {},
surfaceContracts: raw.surfaceContracts ?? {},
topicDecisions: raw.topicDecisions ?? {},
...raw.sourceTurnId !== void 0 ? { sourceTurnId: raw.sourceTurnId } : {},
Expand Down Expand Up @@ -113986,6 +113995,7 @@ function compileMissionTruth(deps4, intakeDeps3, request) {
const decisions = [];
const contracts = [];
const compiledItemIds = [];
const compiledFactItemIds = [];
if (map.fieldsWritten !== true) {
for (const chunk of request.source.chunks) {
if (facts.length >= FACT_BUDGET / 2) break;
Expand All @@ -113998,15 +114008,16 @@ function compileMissionTruth(deps4, intakeDeps3, request) {
});
}
}
const sourceFactCount = facts.length;
const pendingBySurface = /* @__PURE__ */ new Map();
for (const item of request.analysis.items) {
if (blocked2.has(item.itemId)) continue;
if (item.classification === "UNKNOWN_PRODUCT_AUTHORITY") continue;
if (item.classification === "CONTRADICTION") continue;
if (item.classification === "EXISTING_SEALED_CONTRACT_CHANGE") continue;
const bearsContract = item.classification !== "IMPLEMENTATION_DETAIL" && item.classification !== "EXISTING_CONTRACT_COMPATIBLE";
if (map.itemDecisions[item.itemId] === void 0) {
if (bearsContract && decisions.length < decisionBudget) {
if (bearsContract && map.itemDecisions[item.itemId] === void 0) {
if (decisions.length < decisionBudget) {
compiledItemIds.push(item.itemId);
decisions.push({
decision: clip(item.statement, INTAKE_LIMITS.maxTextChars),
Expand All @@ -114015,18 +114026,20 @@ function compileMissionTruth(deps4, intakeDeps3, request) {
sourceTurnId,
topics: item.topics.slice(0, 8)
});
} else if (bearsContract) {
} else {
overflowItemIds.push(item.itemId);
continue;
} else if (facts.length < FACT_BUDGET) {
facts.push({
statement: clip(item.statement, INTAKE_LIMITS.maxTextChars),
provenance: "known-from-user",
sourceTurnId,
topics: item.topics.slice(0, 8)
});
}
}
if (!bearsContract && map.itemFacts[item.itemId] === void 0 && facts.length < FACT_BUDGET) {
compiledFactItemIds.push(item.itemId);
facts.push({
statement: clip(item.statement, INTAKE_LIMITS.maxTextChars),
provenance: "known-from-user",
sourceTurnId,
topics: item.topics.slice(0, 8)
});
}
if (!bearsContract) continue;
if (isExclusion(item)) continue;
if (map.itemContracts[item.itemId] !== void 0) continue;
Expand Down Expand Up @@ -114054,6 +114067,10 @@ function compileMissionTruth(deps4, intakeDeps3, request) {
const decisionId = decisionAssessment.decisionIds[index];
if (itemId !== void 0 && decisionId !== void 0) map.itemDecisions[itemId] = decisionId;
});
compiledFactItemIds.forEach((itemId, index) => {
const factId = decisionAssessment.factIds[sourceFactCount + index];
if (factId !== void 0) map.itemFacts[itemId] = factId;
});
topicDecisionInputs.forEach((_, index) => {
const topic = resolvedTopics[index];
const decisionId = decisionAssessment.decisionIds[decisions.length + index];
Expand Down
37 changes: 27 additions & 10 deletions integrations/claude-code-plugin/specbridge/dist/mcp-server.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -33306,6 +33306,13 @@ function recordAssessment(deps, missionId, input) {
let mission = requireMissionState(deps.workspace, missionId);
assertDiscoveryOpen(mission, "a discovery assessment");
const at = now(deps).toISOString();
const incomingFacts = input.facts?.length ?? 0;
if (mission.counters.facts + incomingFacts > MISSION_LIMITS.maxFacts) {
throw new MissionError(
"SBM006",
`Recording ${incomingFacts} fact(s) would exceed the mission's ${MISSION_LIMITS.maxFacts}-fact bound (${mission.counters.facts} already recorded).`
);
}
const factIds = [];
const questionIds = [];
const decisionIds = [];
Expand Down Expand Up @@ -91228,6 +91235,7 @@ function emptyProjectionMap() {
return {
itemContracts: {},
itemDecisions: {},
itemFacts: {},
surfaceContracts: {},
topicDecisions: {}
};
Expand All @@ -91246,6 +91254,7 @@ function readProjectionMap(workspace, intakeId) {
return {
itemContracts: raw.itemContracts ?? {},
itemDecisions: raw.itemDecisions ?? {},
itemFacts: raw.itemFacts ?? {},
surfaceContracts: raw.surfaceContracts ?? {},
topicDecisions: raw.topicDecisions ?? {},
...raw.sourceTurnId !== void 0 ? { sourceTurnId: raw.sourceTurnId } : {},
Expand Down Expand Up @@ -91366,6 +91375,7 @@ function compileMissionTruth(deps, intakeDeps3, request) {
const decisions = [];
const contracts = [];
const compiledItemIds = [];
const compiledFactItemIds = [];
if (map.fieldsWritten !== true) {
for (const chunk of request.source.chunks) {
if (facts.length >= FACT_BUDGET / 2) break;
Expand All @@ -91378,15 +91388,16 @@ function compileMissionTruth(deps, intakeDeps3, request) {
});
}
}
const sourceFactCount = facts.length;
const pendingBySurface = /* @__PURE__ */ new Map();
for (const item of request.analysis.items) {
if (blocked2.has(item.itemId)) continue;
if (item.classification === "UNKNOWN_PRODUCT_AUTHORITY") continue;
if (item.classification === "CONTRADICTION") continue;
if (item.classification === "EXISTING_SEALED_CONTRACT_CHANGE") continue;
const bearsContract = item.classification !== "IMPLEMENTATION_DETAIL" && item.classification !== "EXISTING_CONTRACT_COMPATIBLE";
if (map.itemDecisions[item.itemId] === void 0) {
if (bearsContract && decisions.length < decisionBudget) {
if (bearsContract && map.itemDecisions[item.itemId] === void 0) {
if (decisions.length < decisionBudget) {
compiledItemIds.push(item.itemId);
decisions.push({
decision: clip(item.statement, INTAKE_LIMITS.maxTextChars),
Expand All @@ -91395,18 +91406,20 @@ function compileMissionTruth(deps, intakeDeps3, request) {
sourceTurnId,
topics: item.topics.slice(0, 8)
});
} else if (bearsContract) {
} else {
overflowItemIds.push(item.itemId);
continue;
} else if (facts.length < FACT_BUDGET) {
facts.push({
statement: clip(item.statement, INTAKE_LIMITS.maxTextChars),
provenance: "known-from-user",
sourceTurnId,
topics: item.topics.slice(0, 8)
});
}
}
if (!bearsContract && map.itemFacts[item.itemId] === void 0 && facts.length < FACT_BUDGET) {
compiledFactItemIds.push(item.itemId);
facts.push({
statement: clip(item.statement, INTAKE_LIMITS.maxTextChars),
provenance: "known-from-user",
sourceTurnId,
topics: item.topics.slice(0, 8)
});
}
if (!bearsContract) continue;
if (isExclusion(item)) continue;
if (map.itemContracts[item.itemId] !== void 0) continue;
Expand Down Expand Up @@ -91434,6 +91447,10 @@ function compileMissionTruth(deps, intakeDeps3, request) {
const decisionId = decisionAssessment.decisionIds[index];
if (itemId !== void 0 && decisionId !== void 0) map.itemDecisions[itemId] = decisionId;
});
compiledFactItemIds.forEach((itemId, index) => {
const factId = decisionAssessment.factIds[sourceFactCount + index];
if (factId !== void 0) map.itemFacts[itemId] = factId;
});
topicDecisionInputs.forEach((_, index) => {
const topic = resolvedTopics[index];
const decisionId = decisionAssessment.decisionIds[decisions.length + index];
Expand Down
8 changes: 4 additions & 4 deletions integrations/codex-plugin/specbridge/dist/checksums.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@
"bytes": 155992
},
"cli.cjs": {
"sha256": "771fd77ef1f3dd42dc91c9bea8bb4fb3672d0edca40dac575646b6d044f8512c",
"bytes": 5858156
"sha256": "db1ed5fb7eacf11662e1206e27b74004cb31f1df88c4ee30b65ce092eb78e377",
"bytes": 5858878
},
"mcp-launcher.cjs": {
"sha256": "205d2730178bcdb5a06e199a42a6a6fb0977f42d706f3d445aec801a60874b3e",
"bytes": 4567
},
"mcp-server.cjs": {
"sha256": "c3ee7b32ff982f9797ea7091aad9f12a0c95e30915cda98c01317219f9146f4c",
"bytes": 3777035
"sha256": "090a7686c19a94495baa75b230899f15a8e0b6036cfb09f73d4482686b621a3e",
"bytes": 3777757
}
}
}
37 changes: 27 additions & 10 deletions integrations/codex-plugin/specbridge/dist/cli.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -55236,6 +55236,13 @@ function recordAssessment(deps4, missionId, input) {
let mission = requireMissionState(deps4.workspace, missionId);
assertDiscoveryOpen(mission, "a discovery assessment");
const at = now(deps4).toISOString();
const incomingFacts = input.facts?.length ?? 0;
if (mission.counters.facts + incomingFacts > MISSION_LIMITS.maxFacts) {
throw new MissionError(
"SBM006",
`Recording ${incomingFacts} fact(s) would exceed the mission's ${MISSION_LIMITS.maxFacts}-fact bound (${mission.counters.facts} already recorded).`
);
}
const factIds = [];
const questionIds = [];
const decisionIds = [];
Expand Down Expand Up @@ -113848,6 +113855,7 @@ function emptyProjectionMap() {
return {
itemContracts: {},
itemDecisions: {},
itemFacts: {},
surfaceContracts: {},
topicDecisions: {}
};
Expand All @@ -113866,6 +113874,7 @@ function readProjectionMap(workspace, intakeId) {
return {
itemContracts: raw.itemContracts ?? {},
itemDecisions: raw.itemDecisions ?? {},
itemFacts: raw.itemFacts ?? {},
surfaceContracts: raw.surfaceContracts ?? {},
topicDecisions: raw.topicDecisions ?? {},
...raw.sourceTurnId !== void 0 ? { sourceTurnId: raw.sourceTurnId } : {},
Expand Down Expand Up @@ -113986,6 +113995,7 @@ function compileMissionTruth(deps4, intakeDeps3, request) {
const decisions = [];
const contracts = [];
const compiledItemIds = [];
const compiledFactItemIds = [];
if (map.fieldsWritten !== true) {
for (const chunk of request.source.chunks) {
if (facts.length >= FACT_BUDGET / 2) break;
Expand All @@ -113998,15 +114008,16 @@ function compileMissionTruth(deps4, intakeDeps3, request) {
});
}
}
const sourceFactCount = facts.length;
const pendingBySurface = /* @__PURE__ */ new Map();
for (const item of request.analysis.items) {
if (blocked2.has(item.itemId)) continue;
if (item.classification === "UNKNOWN_PRODUCT_AUTHORITY") continue;
if (item.classification === "CONTRADICTION") continue;
if (item.classification === "EXISTING_SEALED_CONTRACT_CHANGE") continue;
const bearsContract = item.classification !== "IMPLEMENTATION_DETAIL" && item.classification !== "EXISTING_CONTRACT_COMPATIBLE";
if (map.itemDecisions[item.itemId] === void 0) {
if (bearsContract && decisions.length < decisionBudget) {
if (bearsContract && map.itemDecisions[item.itemId] === void 0) {
if (decisions.length < decisionBudget) {
compiledItemIds.push(item.itemId);
decisions.push({
decision: clip(item.statement, INTAKE_LIMITS.maxTextChars),
Expand All @@ -114015,18 +114026,20 @@ function compileMissionTruth(deps4, intakeDeps3, request) {
sourceTurnId,
topics: item.topics.slice(0, 8)
});
} else if (bearsContract) {
} else {
overflowItemIds.push(item.itemId);
continue;
} else if (facts.length < FACT_BUDGET) {
facts.push({
statement: clip(item.statement, INTAKE_LIMITS.maxTextChars),
provenance: "known-from-user",
sourceTurnId,
topics: item.topics.slice(0, 8)
});
}
}
if (!bearsContract && map.itemFacts[item.itemId] === void 0 && facts.length < FACT_BUDGET) {
compiledFactItemIds.push(item.itemId);
facts.push({
statement: clip(item.statement, INTAKE_LIMITS.maxTextChars),
provenance: "known-from-user",
sourceTurnId,
topics: item.topics.slice(0, 8)
});
}
if (!bearsContract) continue;
if (isExclusion(item)) continue;
if (map.itemContracts[item.itemId] !== void 0) continue;
Expand Down Expand Up @@ -114054,6 +114067,10 @@ function compileMissionTruth(deps4, intakeDeps3, request) {
const decisionId = decisionAssessment.decisionIds[index];
if (itemId !== void 0 && decisionId !== void 0) map.itemDecisions[itemId] = decisionId;
});
compiledFactItemIds.forEach((itemId, index) => {
const factId = decisionAssessment.factIds[sourceFactCount + index];
if (factId !== void 0) map.itemFacts[itemId] = factId;
});
topicDecisionInputs.forEach((_, index) => {
const topic = resolvedTopics[index];
const decisionId = decisionAssessment.decisionIds[decisions.length + index];
Expand Down
Loading
Loading