@entrorove/skill 0.1.62 → 0.1.64

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.
Files changed (51) hide show
  1. package/CAPABILITY-MAP.md +7 -2
  2. package/CHANGELOG.md +10 -0
  3. package/IDE-EXECUTION.md +32 -3
  4. package/REUSE-DISCIPLINE.md +1 -1
  5. package/SKILL.md +6 -2
  6. package/cli-input.mjs +22 -0
  7. package/cli.mjs +2 -8
  8. package/cloud-task-client.mjs +10 -2
  9. package/cloud-task-images.mjs +39 -0
  10. package/ide-exit.mjs +49 -9
  11. package/ide-hook.mjs +2 -2
  12. package/local-contracts.mjs +4 -1
  13. package/local-discipline-gate.mjs +9 -1
  14. package/local-discipline-repository.mjs +11 -5
  15. package/local-finder-plist.mjs +87 -0
  16. package/local-finder-store.mjs +115 -0
  17. package/local-mutation-authority.mjs +11 -0
  18. package/local-mutation-completion-evidence.mjs +83 -0
  19. package/local-mutation-consumption.mjs +33 -10
  20. package/local-mutation-environment-observation.mjs +85 -0
  21. package/local-mutation-finder-observation.mjs +58 -0
  22. package/local-mutation-wire.mjs +26 -8
  23. package/local-scope-files.mjs +3 -1
  24. package/local-scope-font.mjs +45 -0
  25. package/local-scope-repository.mjs +16 -3
  26. package/local-scope-zip.mjs +93 -0
  27. package/manifest.json +1 -1
  28. package/member-producer-repair-authority.mjs +48 -0
  29. package/model-images.d.mts +9 -0
  30. package/model-images.mjs +87 -0
  31. package/mutation-challenge-refresh.mjs +51 -0
  32. package/mutation-client.mjs +42 -24
  33. package/mutation-connection-state.mjs +17 -0
  34. package/package.json +18 -2
  35. package/release-state.json +49 -33
  36. package/release.mjs +8 -0
  37. package/releases.json +12 -0
  38. package/remote-client.mjs +1 -1
  39. package/remote-transport.mjs +48 -16
  40. package/scope-amendment-client.mjs +1 -1
  41. package/scope-amendment-consumption.mjs +32 -0
  42. package/scope-amendment-mutation.mjs +2 -3
  43. package/scope-amendment-observer.mjs +2 -1
  44. package/scope-amendment-remote.mjs +12 -2
  45. package/scope-amendment-retirement.mjs +54 -0
  46. package/scope-amendment-state.mjs +7 -4
  47. package/task-entry-client.mjs +1 -0
  48. package/workflow-observation-client.mjs +11 -0
  49. package/workflow-observation-connection.mjs +2 -1
  50. package/workflow-observation-remote.mjs +26 -1
  51. package/workflow-observation-wire.mjs +6 -3
@@ -51,6 +51,18 @@ function cachedReportPrerequisite(result, pending, state, location) {
51
51
  && next.reuseOriginalInput === true && next.resumeRequestId === pending.requestId && next.preserveOriginalFlow === true
52
52
  && result.feedback?.acknowledgement?.stored === true && result.feedback.resultDigest === sha256(canonical(output));
53
53
  }
54
+ function terminalRejection(result, pending) {
55
+ const output = result?.output, feedback = result?.feedback, ack = feedback?.acknowledgement;
56
+ try { verifyAutomaticFeedback(feedback, pending.requestId, pending.requestId); } catch { return null; }
57
+ if (output?.schemaVersion !== 'entrorove.skill.response/1.0' || output.requestId !== pending.requestId
58
+ || output.status !== 'failed' || feedback.resultDigest !== sha256(canonical(output))
59
+ || feedback.evaluation.operation !== pending.operation || feedback.evaluation.status !== 'failed'
60
+ || ack?.stored !== true || ack.requestId !== pending.requestId || ack.receiptId !== feedback.receiptId
61
+ || ack.generation !== (feedback.generation ?? 1)) return null;
62
+ return { operation: pending.operation, status: 'failed', receiptId: feedback.receiptId,
63
+ generation: feedback.generation ?? 1, acknowledged: true, effects: 'not-inferred',
64
+ ...(/^[a-z][a-z0-9-]{0,63}$/.test(output.error ?? '') ? { error: output.error } : {}) };
65
+ }
54
66
  export async function observationRemote(stage, operation, input, state, location, dependencies) {
55
67
  const requestId = buildInvocation(operation, input).requestId;
56
68
  let response, result;
@@ -79,6 +91,17 @@ export async function observationRemote(stage, operation, input, state, location
79
91
  throw Object.assign(new Error(result.output.message ?? 'Original local observation prerequisite is unresolved'),
80
92
  { code: result.output.code, output: result.output });
81
93
  }
94
+ const rejection = terminalRejection(result, state.pending);
95
+ if (rejection) {
96
+ const failure = { ...state.pending, output: result.output, feedback: result.feedback };
97
+ if (canonical(state.failures?.at(-1) ?? null) !== canonical(failure)) state.failures = [...(state.failures ?? []), failure];
98
+ state.rejection = failure;
99
+ // Keep the original pending binding: a known failure grants no retry,
100
+ // no replacement admission and no second launch of a cached process.
101
+ await saveObservationState(location, state);
102
+ throw Object.assign(new Error('The original observation request failed and its receipt was acknowledged'),
103
+ { code: 'ENTROROVE_LOCAL_OBSERVATION_REJECTED', knownTerminalFailure: true, requestId, rejection });
104
+ }
82
105
  throw unknown(requestId);
83
106
  }
84
107
  state[stage] = result.output; delete state.pending; await saveObservationState(location, state);
@@ -91,9 +114,11 @@ export async function authorizeObservation(admission, dependencies, launching) {
91
114
  const status = parseTransportResponse(response, 'original local observation account');
92
115
  if (!response.ok || status?.schemaVersion !== 'entrorove.flow-status/1.0'
93
116
  || status.flow?.flowId !== admission.flowId || status.flow.ownerId !== admission.ownerId
94
- || launching && (status.flow.stepId !== admission.stepId || status.flow.status !== 'running'
117
+ || launching && (status.flow.stepId !== admission.stepId && !memberProducerRepairStepMatches(status, admission)
118
+ || status.flow.status !== 'running'
95
119
  || status.workflow?.phase !== 'execute' || status.workflow.terminalAt
96
120
  || ['pending', 'declined'].includes(status.workflow.authorization))) {
97
121
  observationFail('Current account cannot confirm its original local observation task and execution step');
98
122
  }
99
123
  }
124
+ import { memberProducerRepairStepMatches } from './member-producer-repair-authority.mjs';
@@ -10,9 +10,11 @@ export function observationExact(value, fields) {
10
10
  || canonical(Object.keys(value).sort()) !== canonical([...fields].sort())) observationFail('Local observation fields are invalid');
11
11
  }
12
12
  export function observationInput(input) {
13
- const fields = Object.hasOwn(input ?? {}, 'settlementId') ? observationIdentityFields : observationReadOnlyIdentityFields;
13
+ const fields = [...(Object.hasOwn(input ?? {}, 'settlementId') ? observationIdentityFields : observationReadOnlyIdentityFields),
14
+ ...(Object.hasOwn(input ?? {}, 'dependencyRepairDigest') ? ['dependencyRepairDigest'] : [])];
14
15
  observationExact(input, fields);
15
- for (const field of fields.filter(field => field !== 'generation')) mutationId14(input[field], field);
16
+ for (const field of fields.filter(field => !['generation', 'dependencyRepairDigest'].includes(field))) mutationId14(input[field], field);
17
+ if (Object.hasOwn(input, 'dependencyRepairDigest') && !/^[a-f0-9]{64}$/.test(input.dependencyRepairDigest)) observationFail('Dependency repair reference must be its exact accepted server digest');
16
18
  if (!Number.isSafeInteger(input.generation) || input.generation < 1) observationFail('Local observation generation is invalid');
17
19
  return input;
18
20
  }
@@ -53,7 +55,8 @@ export function observationAuthoritySignature(value) {
53
55
  }
54
56
  export function observationAdmission(value, input, { allowExpired = false } = {}) {
55
57
  const readOnly = !Object.hasOwn(input, 'settlementId');
56
- const fields = readOnly ? observationReadOnlyIdentityFields : observationIdentityFields;
58
+ const fields = [...(readOnly ? observationReadOnlyIdentityFields : observationIdentityFields),
59
+ ...(Object.hasOwn(input, 'dependencyRepairDigest') ? ['dependencyRepairDigest'] : [])];
57
60
  observationExact(value, [...fields, 'schemaVersion', 'purpose', 'observationId', 'ownerId', 'taskDigest',
58
61
  'chainDigest', 'epoch', 'planId', 'planDigest', 'executionPlanSha256', 'repositoryDigest',
59
62
  ...(readOnly ? ['sourceKind'] : ['settlementDigest']), 'command',