@happyvertical/smrt-ingestion 0.60.5 → 0.60.6
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/FEEDBACK.md +7 -0
- package/PROPOSALS.md +7 -0
- package/dist/chunks/{execution-Clcmi0sj.js → execution-ySzcTXW3.js} +36 -28
- package/dist/chunks/execution-ySzcTXW3.js.map +1 -0
- package/dist/chunks/{feedback-hDSMYjiG.js → feedback-CSi5pVUI.js} +57 -11
- package/dist/chunks/feedback-CSi5pVUI.js.map +1 -0
- package/dist/chunks/{reviewer-instruction-BeOYVCVk.js → reviewer-instruction-Bst9wIak.js} +2 -2
- package/dist/chunks/{reviewer-instruction-BeOYVCVk.js.map → reviewer-instruction-Bst9wIak.js.map} +1 -1
- package/dist/database-conflicts.d.ts +29 -0
- package/dist/database-conflicts.d.ts.map +1 -0
- package/dist/execution.d.ts +13 -2
- package/dist/execution.d.ts.map +1 -1
- package/dist/execution.js +1 -1
- package/dist/feedback.d.ts.map +1 -1
- package/dist/manifest.json +1 -1
- package/dist/models.js +1 -1
- package/dist/models.js.map +1 -1
- package/dist/proposals.d.ts +5 -0
- package/dist/proposals.d.ts.map +1 -1
- package/dist/proposals.js +16 -8
- package/dist/proposals.js.map +1 -1
- package/dist/server.js +3 -3
- package/dist/smrt-knowledge.json +12 -12
- package/package.json +13 -13
- package/dist/chunks/execution-Clcmi0sj.js.map +0 -1
- package/dist/chunks/feedback-hDSMYjiG.js.map +0 -1
package/FEEDBACK.md
CHANGED
|
@@ -220,6 +220,13 @@ pending actions; regenerate their proposals and obtain fresh approval to recover
|
|
|
220
220
|
A preview replay checks the exact persisted proposal it returns, including its
|
|
221
221
|
analysis attempt; a newer action revision cannot supply replacement lineage.
|
|
222
222
|
Plan replay and final sealed plan-step publication use the same gate.
|
|
223
|
+
Reading examples (retrieval and every selection re-check) takes no exclusive
|
|
224
|
+
lock on a source item (#4651): each source is loaded before and after its
|
|
225
|
+
checks, both loads must agree (review binding and analysis revision), and a
|
|
226
|
+
retention narrowing writes the row only when it actually narrows. Parallel
|
|
227
|
+
reads therefore cannot deadlock on PostgreSQL by visiting source items in
|
|
228
|
+
different orders. A database error inside an example check is never treated as
|
|
229
|
+
an excluded example: it propagates and ends the read.
|
|
223
230
|
For already successful actions, current-authorized durable outcomes remain
|
|
224
231
|
readable/replayable, but invalid learned lineage suppresses saved proposal
|
|
225
232
|
display, arguments and plan payload. An empty selection carries no learned source
|
package/PROPOSALS.md
CHANGED
|
@@ -497,6 +497,13 @@ like `reviewSuggestion`, never enter frozen configuration, digests or
|
|
|
497
497
|
`proposalReadConfiguration`. A reviewer can still re-run a finally failed item
|
|
498
498
|
with "Try again" (REVIEW.md, `retryInterpretation`).
|
|
499
499
|
|
|
500
|
+
Independently of `retry`, a PostgreSQL deadlock (`40P01`) or serialization
|
|
501
|
+
failure (`40001`) in the database reads around the provider call (candidate
|
|
502
|
+
discovery, feedback retrieval and the provider-boundary re-checks) re-runs that
|
|
503
|
+
read up to five times with a short jittered pause (#4651). It is never
|
|
504
|
+
published as a failed attempt: one that outlasts those runs is thrown from
|
|
505
|
+
`generate`, leaving the attempt unpublished for the next lease claim.
|
|
506
|
+
|
|
500
507
|
### Failed-attempt capture (opt-in, #4285)
|
|
501
508
|
|
|
502
509
|
The value-free reason cannot show what the model actually sent. A host that
|
|
@@ -6685,6 +6685,9 @@ function strings(value) {
|
|
|
6685
6685
|
function time(value) {
|
|
6686
6686
|
return new Date(value).getTime();
|
|
6687
6687
|
}
|
|
6688
|
+
function byItem([a], [b]) {
|
|
6689
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
6690
|
+
}
|
|
6688
6691
|
var IntakeExecutionService = class IntakeExecutionService {
|
|
6689
6692
|
constructor(options, config) {
|
|
6690
6693
|
this.options = options;
|
|
@@ -6718,14 +6721,14 @@ var IntakeExecutionService = class IntakeExecutionService {
|
|
|
6718
6721
|
} catch (error) {
|
|
6719
6722
|
if (error instanceof RetentionExpired) intents.set(error.itemId, Math.min(intents.get(error.itemId) ?? Infinity, error.deadline));
|
|
6720
6723
|
if (intents.size) await withEmbeddedWriteTransaction(this.db, isEmbeddedDatabase(this.db), async (db) => {
|
|
6721
|
-
for (const [itemId, deadline] of intents) await this.restoreRetention(db, itemId, deadline);
|
|
6724
|
+
for (const [itemId, deadline] of [...intents].sort(byItem)) await this.restoreRetention(db, itemId, deadline);
|
|
6722
6725
|
});
|
|
6723
6726
|
throw error;
|
|
6724
6727
|
}
|
|
6725
6728
|
}
|
|
6726
6729
|
async restoreRetention(db, itemId, deadline) {
|
|
6727
6730
|
const expiry = new Date(deadline).toISOString();
|
|
6728
|
-
const item = (await db.query("UPDATE intake_items SET expires_at
|
|
6731
|
+
const item = (await db.query("UPDATE intake_items SET expires_at=? WHERE id=? AND tenant_id=? AND confidential_scope_id=? AND expires_at>? RETURNING id,expires_at,visibility", expiry, itemId, this.scope.tenantId, this.scope.confidentialScopeId, expiry)).rows[0] ?? (await db.query("SELECT id,expires_at,visibility FROM intake_items WHERE id=? AND tenant_id=? AND confidential_scope_id=?", itemId, this.scope.tenantId, this.scope.confidentialScopeId)).rows[0];
|
|
6729
6732
|
if (!item) throw new IntakeAccessDeniedError();
|
|
6730
6733
|
if (!this.retained(item)) await this.redactExecution(db, item);
|
|
6731
6734
|
return item;
|
|
@@ -6741,13 +6744,18 @@ var IntakeExecutionService = class IntakeExecutionService {
|
|
|
6741
6744
|
"intake_dispositions"
|
|
6742
6745
|
]) await db.query(`UPDATE ${table} SET data='{}' WHERE item_id=? AND tenant_id=? AND confidential_scope_id=?`, item.id, this.scope.tenantId, this.scope.confidentialScopeId);
|
|
6743
6746
|
}
|
|
6744
|
-
async narrowRetention(db, item, deadline) {
|
|
6745
|
-
const current = await this.item(db, String(item.id),
|
|
6747
|
+
async narrowRetention(db, item, deadline, exclusive = true) {
|
|
6748
|
+
const current = await this.item(db, String(item.id), exclusive, true);
|
|
6746
6749
|
const effective = Math.min(time(current.expires_at), deadline);
|
|
6747
6750
|
if (!Number.isFinite(effective)) throw new Error("Invalid retention deadline");
|
|
6748
|
-
|
|
6749
|
-
|
|
6750
|
-
|
|
6751
|
+
let stored = current;
|
|
6752
|
+
if (effective < time(current.expires_at)) {
|
|
6753
|
+
const expiry = new Date(effective).toISOString();
|
|
6754
|
+
await db.query(`UPDATE intake_items SET expires_at=? WHERE id=? AND tenant_id=? AND confidential_scope_id=?${exclusive ? "" : " AND expires_at>?"}`, expiry, item.id, this.scope.tenantId, this.scope.confidentialScopeId, ...exclusive ? [] : [expiry]);
|
|
6755
|
+
if (!exclusive) stored = await this.item(db, String(item.id), false, true);
|
|
6756
|
+
}
|
|
6757
|
+
item.expires_at = new Date(Math.min(effective, time(stored.expires_at))).toISOString();
|
|
6758
|
+
item.visibility = stored.visibility;
|
|
6751
6759
|
if (!this.retained(item)) await this.redactExecution(db, item);
|
|
6752
6760
|
}
|
|
6753
6761
|
async rows(db, table, where = "", params = []) {
|
|
@@ -6856,13 +6864,13 @@ var IntakeExecutionService = class IntakeExecutionService {
|
|
|
6856
6864
|
deadline
|
|
6857
6865
|
};
|
|
6858
6866
|
}
|
|
6859
|
-
async access(db, item, handler, operation) {
|
|
6867
|
+
async access(db, item, handler, operation, exclusive = true) {
|
|
6860
6868
|
const { current, ceiling, policy, deadline } = await this.authority(db, item, handler, operation);
|
|
6861
6869
|
const enforce = async (executor) => {
|
|
6862
6870
|
const intents = this.retentionIntents.getStore();
|
|
6863
6871
|
const itemId = String(item.id);
|
|
6864
6872
|
intents?.set(itemId, Math.min(intents.get(itemId) ?? Infinity, deadline));
|
|
6865
|
-
await this.narrowRetention(executor, item, deadline);
|
|
6873
|
+
await this.narrowRetention(executor, item, deadline, exclusive);
|
|
6866
6874
|
};
|
|
6867
6875
|
if (db === this.db) await this.tx(enforce);
|
|
6868
6876
|
else await enforce(db);
|
|
@@ -6892,8 +6900,8 @@ var IntakeExecutionService = class IntakeExecutionService {
|
|
|
6892
6900
|
permissions: intersect(strings(current.permissions), ceiling.permissions)
|
|
6893
6901
|
};
|
|
6894
6902
|
}
|
|
6895
|
-
async principal(db, item, handler, operation, work) {
|
|
6896
|
-
const access = await this.access(db, item, handler, operation);
|
|
6903
|
+
async principal(db, item, handler, operation, work, exclusive = true) {
|
|
6904
|
+
const access = await this.access(db, item, handler, operation, exclusive);
|
|
6897
6905
|
const registered = ObjectRegistry.getClassByQualifiedName(handler.operation.model);
|
|
6898
6906
|
const tool = `${registered.collection}.${handler.operation.action}`;
|
|
6899
6907
|
return executeAsPrincipal({
|
|
@@ -6937,23 +6945,23 @@ var IntakeExecutionService = class IntakeExecutionService {
|
|
|
6937
6945
|
id: id2
|
|
6938
6946
|
})), requireReview);
|
|
6939
6947
|
const result = await work(db, authorize);
|
|
6940
|
-
for (const [retainedItemId, deadline] of this.retentionIntents.getStore() ?? []) {
|
|
6948
|
+
for (const [retainedItemId, deadline] of [...this.retentionIntents.getStore() ?? []].sort(byItem)) {
|
|
6941
6949
|
const item = await this.restoreRetention(db, retainedItemId, deadline);
|
|
6942
6950
|
if (!this.retained(item)) throw new RetentionExpired(retainedItemId, deadline);
|
|
6943
6951
|
}
|
|
6944
6952
|
return result;
|
|
6945
6953
|
}));
|
|
6946
6954
|
}
|
|
6947
|
-
async discoveryContext(db, itemId, handlerId, handlerVersion, work, requireReview = false, revalidate) {
|
|
6955
|
+
async discoveryContext(db, itemId, handlerId, handlerVersion, work, requireReview = false, revalidate, exclusive = true) {
|
|
6948
6956
|
const review = async () => {
|
|
6949
|
-
const item = await this.item(db, itemId,
|
|
6950
|
-
await this.access(db, item, this.handler(handlerId, handlerVersion), "review");
|
|
6957
|
+
const item = await this.item(db, itemId, exclusive);
|
|
6958
|
+
await this.access(db, item, this.handler(handlerId, handlerVersion), "review", exclusive);
|
|
6951
6959
|
};
|
|
6952
6960
|
const authorize = async (callback) => {
|
|
6953
|
-
const item = await this.item(db, itemId,
|
|
6961
|
+
const item = await this.item(db, itemId, exclusive);
|
|
6954
6962
|
const handler = this.handler(handlerId, handlerVersion);
|
|
6955
|
-
if ("execution" in handler) return this.principal(db, item, this.operation(handler), "preview", callback);
|
|
6956
|
-
const { context } = await this.access(db, item, handler, "preview");
|
|
6963
|
+
if ("execution" in handler) return this.principal(db, item, this.operation(handler), "preview", callback, exclusive);
|
|
6964
|
+
const { context } = await this.access(db, item, handler, "preview", exclusive);
|
|
6957
6965
|
const resolved = await resolvePlaybook(handler.operation.playbookKey, {
|
|
6958
6966
|
db,
|
|
6959
6967
|
tenantId: this.scope.tenantId,
|
|
@@ -6969,7 +6977,7 @@ var IntakeExecutionService = class IntakeExecutionService {
|
|
|
6969
6977
|
if (operation.kind !== "operation") throw new Error("Playbook unavailable");
|
|
6970
6978
|
const found = this.config.handlers.find((candidate) => "execution" in candidate && candidate.operation.model === operation.model && candidate.operation.action === operation.action);
|
|
6971
6979
|
if (!found) throw new Error("Handler unavailable");
|
|
6972
|
-
await this.principal(db, item, this.operation(found), "preview", async () => {});
|
|
6980
|
+
await this.principal(db, item, this.operation(found), "preview", async () => {}, exclusive);
|
|
6973
6981
|
}
|
|
6974
6982
|
return callback(context);
|
|
6975
6983
|
};
|
|
@@ -7045,15 +7053,15 @@ var IntakeExecutionService = class IntakeExecutionService {
|
|
|
7045
7053
|
}
|
|
7046
7054
|
/** Same-executor current review/evidence/target gate for the owning feedback ledger. */
|
|
7047
7055
|
/** Join an existing owning transaction; its outer boundary restores retention after rollback. */
|
|
7048
|
-
[feedbackDiscoveryContext](db, itemId, handlerId, handlerVersion, work, revalidate) {
|
|
7049
|
-
const run = (executor) => this.discoveryContext(executor, itemId, handlerId, handlerVersion, work, false, revalidate);
|
|
7056
|
+
[feedbackDiscoveryContext](db, itemId, handlerId, handlerVersion, work, revalidate, exclusive = true) {
|
|
7057
|
+
const run = (executor) => this.discoveryContext(executor, itemId, handlerId, handlerVersion, work, false, revalidate, exclusive);
|
|
7050
7058
|
return db ? run(db) : this.tx(run);
|
|
7051
7059
|
}
|
|
7052
|
-
[feedbackActionTransaction](actionId, reviewer, work, executor, requiredProviders, proposalId, targetRevisions = true) {
|
|
7060
|
+
[feedbackActionTransaction](actionId, reviewer, work, executor, requiredProviders, proposalId, targetRevisions = true, exclusive = true) {
|
|
7053
7061
|
const operation = async (db) => {
|
|
7054
7062
|
const load = async () => {
|
|
7055
|
-
const bound = await this.bound(db, actionId,
|
|
7056
|
-
const { context, permissions } = await this.access(db, bound.item, bound.handler, reviewer ? "review" : "read");
|
|
7063
|
+
const bound = await this.bound(db, actionId, exclusive, false, proposalId);
|
|
7064
|
+
const { context, permissions } = await this.access(db, bound.item, bound.handler, reviewer ? "review" : "read", exclusive);
|
|
7057
7065
|
if (requiredProviders?.some((provider) => !context.policy.providers.includes(provider))) throw new Error("Feedback source provider unavailable");
|
|
7058
7066
|
await this.verifyEvidence(db, bound);
|
|
7059
7067
|
for (const target of bound.binding.targetPreconditions) await context.assertTarget(target.model, target.id, bound.action.state === "succeeded" || !targetRevisions ? void 0 : target.revision);
|
|
@@ -7063,7 +7071,7 @@ var IntakeExecutionService = class IntakeExecutionService {
|
|
|
7063
7071
|
const data2 = object(plan.data);
|
|
7064
7072
|
await this.discoveryContext(db, String(bound.item.id), String(data2.handlerId), String(data2.handlerVersion), async (parent) => {
|
|
7065
7073
|
for (const target of object(data2.preview).targetPreconditions) await parent.assertTarget(target.model, target.id, bound.action.state === "succeeded" ? void 0 : target.revision);
|
|
7066
|
-
}, reviewer);
|
|
7074
|
+
}, reviewer, void 0, exclusive);
|
|
7067
7075
|
}
|
|
7068
7076
|
const [analysis] = await this.rows(db, "intake_analyses", "id=?", [bound.proposal.analysis_id]);
|
|
7069
7077
|
const [attempt] = await this.rows(db, "intake_analysis_attempts", "id=?", [bound.proposal.analysis_attempt_id]);
|
|
@@ -7109,7 +7117,7 @@ var IntakeExecutionService = class IntakeExecutionService {
|
|
|
7109
7117
|
const before = await load();
|
|
7110
7118
|
const result = await work(before);
|
|
7111
7119
|
const after = await load();
|
|
7112
|
-
if (intakeBindingDigest(before.review) !== intakeBindingDigest(after.review)) throw new Error("Feedback binding changed");
|
|
7120
|
+
if (intakeBindingDigest(before.review) !== intakeBindingDigest(after.review) || !exclusive && before.context.analysisRevision !== after.context.analysisRevision) throw new Error("Feedback binding changed");
|
|
7113
7121
|
if (after.permissions.some((permission) => !before.permissions.includes(permission))) throw new Error("Feedback cannot widen permissions");
|
|
7114
7122
|
const prior = before.context.policy, next = after.context.policy;
|
|
7115
7123
|
for (const key of [
|
|
@@ -7144,7 +7152,7 @@ var IntakeExecutionService = class IntakeExecutionService {
|
|
|
7144
7152
|
if (!Array.isArray(references)) throw new Error("Feedback lineage unavailable");
|
|
7145
7153
|
if (references.length === 0) return;
|
|
7146
7154
|
if (!this.options.feedback) throw new Error("Feedback configuration unavailable");
|
|
7147
|
-
const { IntakeFeedbackService } = await import("./feedback-
|
|
7155
|
+
const { IntakeFeedbackService } = await import("./feedback-CSi5pVUI.js").then((n) => n.r);
|
|
7148
7156
|
await new IntakeFeedbackService(this.options, this).assertActionLineage(String(bound.action.id), db, String(bound.proposal.id));
|
|
7149
7157
|
}
|
|
7150
7158
|
async getAction(actionId) {
|
|
@@ -8729,4 +8737,4 @@ async function continueIntakeReview(service, actionId, task) {
|
|
|
8729
8737
|
//#endregion
|
|
8730
8738
|
export { __toESM as A, storedFailureCapture as C, generationSnapshotRead as D, discoveryTransaction as E, listReadGate as O, prepareFailureCapture as S, completeWithFailureCapture as T, HandlerArgumentsInvalidError as _, resolveIntakePolicy as a, FAILURE_CAPTURE_MAX_BYTES as b, HANDLER_ARGUMENT_ISSUE_LIMIT as c, schemaOwnedPath as d, require_ajv as f, GenerationSourceStaleError as g, GenerationSnapshotStaleError as h, intakeBindingDigest as i, __exportAll as k, HANDLER_ARGUMENT_PATH_LIMIT as l, redactedCeiling as m, IntakeExecutionService as n, feedbackActionTransaction as o, UNFINISHED_ACTION_STATES as p, continueIntakeReview as r, feedbackDiscoveryContext as s, IntakeAccessDeniedError as t, describeArgumentRefusal as u, ProposalsNotConfiguredError as v, analysisLeaseRemaining as w, assertFailureCapture as x, FAILURE_CAPTURE_DEFAULT_MAX_BYTES as y };
|
|
8731
8739
|
|
|
8732
|
-
//# sourceMappingURL=execution-
|
|
8740
|
+
//# sourceMappingURL=execution-ySzcTXW3.js.map
|