@weiliang0121/capix-records 0.0.0-stage → 0.2.0

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 (107) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +28 -2
  3. package/dist/attempt/helper.d.ts +12 -0
  4. package/dist/attempt/helper.js +2 -0
  5. package/dist/attempt/record.d.ts +15 -0
  6. package/dist/attempt/record.js +2 -0
  7. package/dist/book.d.ts +15 -0
  8. package/dist/book.js +2 -0
  9. package/dist/callable/helper.d.ts +5 -0
  10. package/dist/callable/helper.js +2 -0
  11. package/dist/callable/record.d.ts +18 -0
  12. package/dist/callable/record.js +2 -0
  13. package/dist/composite.d.ts +13 -0
  14. package/dist/composite.js +2 -0
  15. package/dist/construction.d.ts +14 -0
  16. package/dist/construction.js +2 -0
  17. package/dist/content.d.ts +10 -0
  18. package/dist/content.js +2 -0
  19. package/dist/data/archive.d.ts +9 -0
  20. package/dist/data/archive.js +2 -0
  21. package/dist/data/changes.d.ts +43 -0
  22. package/dist/data/changes.js +1 -0
  23. package/dist/data/index.d.ts +8 -0
  24. package/dist/data/index.js +2 -0
  25. package/dist/data/invocation.d.ts +10 -0
  26. package/dist/data/invocation.js +2 -0
  27. package/dist/data/memory.d.ts +26 -0
  28. package/dist/data/memory.js +2 -0
  29. package/dist/data/resource.d.ts +10 -0
  30. package/dist/data/resource.js +1 -0
  31. package/dist/data/transcript.d.ts +19 -0
  32. package/dist/data/transcript.js +1 -0
  33. package/dist/data/types.d.ts +189 -0
  34. package/dist/data/types.js +1 -0
  35. package/dist/data/validate.d.ts +4 -0
  36. package/dist/data/validate.js +2 -0
  37. package/dist/error.d.ts +5 -0
  38. package/dist/error.js +2 -0
  39. package/dist/execution/helper.d.ts +16 -0
  40. package/dist/execution/helper.js +2 -0
  41. package/dist/execution/record.d.ts +8 -0
  42. package/dist/execution/record.js +2 -0
  43. package/dist/index.d.ts +31 -0
  44. package/dist/index.js +2 -0
  45. package/dist/invocation/boundary/helper.d.ts +18 -0
  46. package/dist/invocation/boundary/helper.js +2 -0
  47. package/dist/invocation/boundary/record.d.ts +16 -0
  48. package/dist/invocation/boundary/record.js +2 -0
  49. package/dist/invocation/helper.d.ts +5 -0
  50. package/dist/invocation/helper.js +2 -0
  51. package/dist/invocation/record.d.ts +20 -0
  52. package/dist/invocation/record.js +2 -0
  53. package/dist/memory/helper.d.ts +7 -0
  54. package/dist/memory/helper.js +2 -0
  55. package/dist/memory/observe.d.ts +9 -0
  56. package/dist/memory/observe.js +2 -0
  57. package/dist/memory/record.d.ts +21 -0
  58. package/dist/memory/record.js +2 -0
  59. package/dist/operation/helper.d.ts +12 -0
  60. package/dist/operation/helper.js +2 -0
  61. package/dist/operation/record.d.ts +17 -0
  62. package/dist/operation/record.js +2 -0
  63. package/dist/record.d.ts +16 -0
  64. package/dist/record.js +2 -0
  65. package/dist/recorder.d.ts +28 -0
  66. package/dist/recorder.js +2 -0
  67. package/dist/registration.d.ts +10 -0
  68. package/dist/registration.js +2 -0
  69. package/dist/resource/record.d.ts +15 -0
  70. package/dist/resource/record.js +2 -0
  71. package/dist/resource.d.ts +15 -0
  72. package/dist/resource.js +2 -0
  73. package/dist/restoration/access.d.ts +3 -0
  74. package/dist/restoration/access.js +2 -0
  75. package/dist/restoration/check.d.ts +2 -0
  76. package/dist/restoration/check.js +2 -0
  77. package/dist/restoration/entry.d.ts +3 -0
  78. package/dist/restoration/entry.js +2 -0
  79. package/dist/restoration/tree.d.ts +2 -0
  80. package/dist/restoration/tree.js +2 -0
  81. package/dist/root/helper.d.ts +5 -0
  82. package/dist/root/helper.js +2 -0
  83. package/dist/root/record.d.ts +6 -0
  84. package/dist/root/record.js +2 -0
  85. package/dist/runtime/record.d.ts +9 -0
  86. package/dist/runtime/record.js +2 -0
  87. package/dist/source.d.ts +6 -0
  88. package/dist/source.js +1 -0
  89. package/dist/transcript/helper.d.ts +6 -0
  90. package/dist/transcript/helper.js +2 -0
  91. package/dist/transcript/record.d.ts +20 -0
  92. package/dist/transcript/record.js +2 -0
  93. package/dist/tree/access.d.ts +3 -0
  94. package/dist/tree/access.js +2 -0
  95. package/dist/tree/relation.d.ts +4 -0
  96. package/dist/tree/relation.js +2 -0
  97. package/dist/tree/tree.d.ts +17 -0
  98. package/dist/tree/tree.js +2 -0
  99. package/dist/value/check.d.ts +1 -0
  100. package/dist/value/check.js +2 -0
  101. package/dist/value/copy.d.ts +1 -0
  102. package/dist/value/copy.js +2 -0
  103. package/dist/value/freeze.d.ts +1 -0
  104. package/dist/value/freeze.js +2 -0
  105. package/dist/value/snapshot.d.ts +1 -0
  106. package/dist/value/snapshot.js +2 -0
  107. package/package.json +53 -3
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 wei.liang (https://github.com/weiliang0121)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,29 @@
1
- # Temporary Holding Version
1
+ # @weiliang0121/capix-records
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Optional recording entities and resource packages/contracts for CAPiX.
4
+
5
+ ES modules and TypeScript declarations. Requires Node.js 22.23.2 or newer.
6
+
7
+ ```sh
8
+ npm install @weiliang0121/capix-records
9
+ ```
10
+
11
+ ## Public entry points
12
+
13
+ - `@weiliang0121/capix-records`
14
+ - `@weiliang0121/capix-records/construction`
15
+ - `@weiliang0121/capix-records/data`
16
+
17
+ The root entry exports live record entities and recording helpers. The `data` entry owns their plain record shapes, archive identities, change records, output resolution, and full subtree/body validation. It has no Node.js or live-entity imports and is suitable for browser and wire consumers. Identically named data interfaces and entity classes are deliberately separated by these entries.
18
+
19
+ `CallableRecordHelper.snapshot` reads the caller-selected invocation subtree and its actual ancestor path; selecting a business task, Observer overview, and environment aggregation remain application responsibilities. `ExecutionRecordHelper.snapshot` and the corresponding legacy-named validators retain their existing record representation and validation; these APIs do not upgrade old data or resume execution. Memory recording and `observeMemory` expose only `MemoryRecordContent` (`content`) and available records, not arbitrary metadata or recovery material.
20
+
21
+ This ownership change removes the dependency on `capix-protocol`. Consumers of the former protocol recording/archive exports must import `capix-records/data`; shared invocation vocabulary belongs to `capix-contracts`.
22
+
23
+ `ResourceRecord.sequence` retains the owning call's shared resource order, which also numbers forwarded domain facts. Because those facts are projected separately or intentionally left uninterpreted, resource record numbers may have gaps. Subtree validation and record-book restoration require positive safe integers in strictly increasing order per owner; identity, binding phases, and started/returned/threw pairing remain checked. Missing numbers do not establish missing effects or authorize replay.
24
+
25
+ This package is part of CAPiX. The npm distribution contains compiled JavaScript, type declarations, and this package's MIT license. Reference services and client applications are not included in this package or the initial npm release.
26
+
27
+ ## License
28
+
29
+ MIT. Copyright (c) 2026 wei.liang. See [LICENSE](LICENSE).
@@ -0,0 +1,12 @@
1
+ import type { InvocationFailureFact, RuntimeErrorValue } from '@weiliang0121/capix-contracts';
2
+ import type { Recorder } from '../recorder.js';
3
+ import type { RecordBook } from '../book.js';
4
+ import { AttemptRecord, type AttemptRecordOptions } from './record.js';
5
+ export declare class AttemptRecordHelper {
6
+ static create(recorder: Recorder, options: AttemptRecordOptions, input: unknown): AttemptRecord;
7
+ static get(book: RecordBook, id: string): AttemptRecord;
8
+ static findByOperation(recorder: Recorder, operationId: string): readonly AttemptRecord[];
9
+ static complete(recorder: Recorder, id: string, output: unknown, resultOf?: number): void;
10
+ static fail(recorder: Recorder, id: string, error: RuntimeErrorValue, failure?: InvocationFailureFact): void;
11
+ private static owner;
12
+ }
@@ -0,0 +1,2 @@
1
+ /*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
2
+ var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});import{InvocationRecordHelper}from"../invocation/helper.js";import{ExecutionRecord}from"../execution/record.js";import{OperationRecord}from"../operation/record.js";import{AttemptRecord}from"./record.js";class AttemptRecordHelper{static{__name(this,"AttemptRecordHelper")}static create(recorder,options,input){const book=recorder.book,operation=this.owner(book,options.operationId),execution=book.get(operation.executionId);if(!(execution instanceof ExecutionRecord))throw new Error("Execution does not exist");if(execution.status!=="running"||operation.status!=="running")throw new Error("Record has already ended");const record=new AttemptRecord(options,input);return recorder.add(record)}static get(book,id){const record=book.get(id);if(!(record instanceof AttemptRecord))throw new Error("Attempt does not exist");return record}static findByOperation(recorder,operationId){return this.owner(recorder.book,operationId),recorder.tree.children(operationId).filter(record=>record instanceof AttemptRecord)}static complete(recorder,id,output,resultOf){InvocationRecordHelper.finish(recorder,this.get(recorder.book,id),record=>record.complete(output,resultOf))}static fail(recorder,id,error,failure){InvocationRecordHelper.finish(recorder,this.get(recorder.book,id),record=>record.fail(error,failure))}static owner(book,id){const operation=book.get(id);if(!(operation instanceof OperationRecord))throw new Error("Operation does not exist");return operation}}export{AttemptRecordHelper};
@@ -0,0 +1,15 @@
1
+ import type { AttemptRecord as AttemptData, AttemptValue } from '../data/index.js';
2
+ import { InvocationRecord } from '../invocation/record.js';
3
+ export type AttemptRecordOptions = Omit<AttemptData, 'id' | 'value' | 'status' | 'parentId' | 'childIds'>;
4
+ export declare class AttemptRecord extends InvocationRecord<AttemptValue> implements AttemptData {
5
+ readonly kind: "attempt";
6
+ readonly contextId: string;
7
+ readonly operationId: string;
8
+ readonly name: string;
9
+ readonly label: string;
10
+ readonly source: string;
11
+ readonly caller: string;
12
+ readonly callee: string;
13
+ constructor(options: AttemptRecordOptions, input: unknown);
14
+ toJSON(): AttemptData;
15
+ }
@@ -0,0 +1,2 @@
1
+ /*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
2
+ var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});import{pick}from"es-toolkit/object";import{InvocationRecord}from"../invocation/record.js";import{snapshotValue}from"../value/snapshot.js";class AttemptRecord extends InvocationRecord{static{__name(this,"AttemptRecord")}kind="attempt";contextId;operationId;name;label;source;caller;callee;constructor(options,input){super(snapshotValue({input,processes:[],relationChanges:[]}),options.operationId),this.contextId=options.contextId,this.operationId=options.operationId,this.name=options.name,this.label=options.label,this.source=options.source,this.caller=options.caller,this.callee=options.callee,Object.freeze(this)}toJSON(){return{...super.toJSON(),status:this.status,...pick(this,["contextId","operationId","name","label","source","caller","callee"])}}}export{AttemptRecord};
package/dist/book.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ import type { BaseRecord } from './record.js';
2
+ import { removeRegistration } from './tree/access.js';
3
+ import type { RecordEntry } from './data/index.js';
4
+ export interface RecordBookState {
5
+ readonly entries: readonly RecordEntry[];
6
+ }
7
+ export declare class RecordBook {
8
+ #private;
9
+ static restore(state: RecordBookState): RecordBook;
10
+ exportState(): RecordBookState;
11
+ add<RecordType extends BaseRecord<unknown>>(record: RecordType): RecordType;
12
+ [removeRegistration](record: BaseRecord<unknown>): void;
13
+ get(id: string): BaseRecord<unknown> | undefined;
14
+ values(): IterableIterator<BaseRecord<unknown>>;
15
+ }
package/dist/book.js ADDED
@@ -0,0 +1,2 @@
1
+ /*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
2
+ var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});import{removeRegistration}from"./tree/access.js";import{isPlainObject}from"es-toolkit/predicate";import{snapshotValue}from"./value/snapshot.js";import{restoreEntry}from"./restoration/entry.js";import{checkRestoredTree}from"./restoration/tree.js";import{sealHistorical}from"./restoration/access.js";class RecordBook{static{__name(this,"RecordBook")}#records=new Map;static restore(state){if(!isPlainObject(state)||!Array.isArray(state.entries)||Object.keys(state).length!==1)throw new Error("Invalid stored record book");const captured=snapshotValue(state),book=new RecordBook;for(const entry of captured.entries)book.add(restoreEntry(entry));checkRestoredTree(book);for(const record of book.values())record[sealHistorical]();return book}exportState(){return snapshotValue({entries:[...this.#records.values()].map(record=>({kind:record.kind,data:record.toJSON()}))})}add(record){if(this.#records.has(record.id))throw new Error("Record ID already exists");return this.#records.set(record.id,record),record}[removeRegistration](record){this.#records.get(record.id)===record&&this.#records.delete(record.id)}get(id){return this.#records.get(id)}values(){return this.#records.values()}}export{RecordBook};
@@ -0,0 +1,5 @@
1
+ import type { ExecutionRecordSnapshot } from '../data/index.js';
2
+ import type { Recorder } from '../recorder.js';
3
+ export declare class CallableRecordHelper {
4
+ static snapshot(recorder: Recorder, id: string): ExecutionRecordSnapshot;
5
+ }
@@ -0,0 +1,2 @@
1
+ /*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
2
+ var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});import{InvocationBoundaryRecord}from"../invocation/boundary/record.js";import{MemoryRecord}from"../memory/record.js";import{ResourceRecord}from"../resource/record.js";import{TranscriptRecord}from"../transcript/record.js";import{CallableRecord}from"./record.js";class CallableRecordHelper{static{__name(this,"CallableRecordHelper")}static snapshot(recorder,id){const selected=recorder.book.get(id);if(!(selected instanceof CallableRecord))throw new Error("Callable record does not exist");const records=[selected,...recorder.tree.descendants(id)];let root=selected;const ancestry=[],visited=new Set([selected.id]);let parent=root.parentId?recorder.book.get(root.parentId):void 0;for(;parent instanceof CallableRecord;){if(visited.has(parent.id)||!parent.childIds.includes(root.id))throw new Error("Inconsistent callable record ancestry");visited.add(parent.id),ancestry.unshift(parent),root=parent,parent=root.parentId?recorder.book.get(root.parentId):void 0}const ancestorDetails=ancestry.flatMap(ancestor=>recorder.tree.children(ancestor.id)),boundaries=[...ancestorDetails.filter(record=>record instanceof InvocationBoundaryRecord),...records.filter(record=>record instanceof InvocationBoundaryRecord)];return boundaries.sort((left,right)=>left.scopeId===right.scopeId?left.sequence-right.sequence:Date.parse(left.occurredAt)-Date.parse(right.occurredAt)),{execution:selected.toJSON(),calls:records.filter(record=>record instanceof CallableRecord).map(record=>record.toJSON()),...root===selected?{}:{rootCall:root.toJSON()},...ancestry.length>1?{ancestors:ancestry.slice(1).map(record=>record.toJSON())}:{},boundaries:boundaries.map(record=>record.toJSON()),resources:[...ancestorDetails,...records].filter(record=>record instanceof ResourceRecord).map(record=>record.toJSON()),transcripts:records.filter(record=>record instanceof TranscriptRecord).map(record=>record.toJSON()),memories:records.filter(record=>record instanceof MemoryRecord).map(record=>record.toJSON())}}}export{CallableRecordHelper};
@@ -0,0 +1,18 @@
1
+ import type { CallableRecord as CallableRecordData, CallableValue } from '../data/index.js';
2
+ import { InvocationRecord } from '../invocation/record.js';
3
+ export type CallableRecordOptions = Omit<CallableRecordData, 'id' | 'value' | 'status' | 'childIds'>;
4
+ export declare class CallableRecord extends InvocationRecord<CallableValue> implements CallableRecordData {
5
+ readonly kind: "invocation";
6
+ readonly contextId: string;
7
+ readonly structureKind: CallableRecordData['structureKind'];
8
+ readonly structureId?: string;
9
+ readonly name?: string;
10
+ readonly label?: string;
11
+ readonly source?: string;
12
+ readonly callee?: string;
13
+ readonly role?: string;
14
+ constructor(options: CallableRecordOptions, value: Omit<CallableValue, 'processes' | 'relationChanges'> & {
15
+ startedAt: string;
16
+ });
17
+ toJSON(): CallableRecordData;
18
+ }
@@ -0,0 +1,2 @@
1
+ /*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
2
+ var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});import{InvocationRecord}from"../invocation/record.js";import{snapshotValue}from"../value/snapshot.js";class CallableRecord extends InvocationRecord{static{__name(this,"CallableRecord")}kind="invocation";contextId;structureKind;structureId;name;label;source;callee;role;constructor(options,value){super(snapshotValue({...value,processes:[],relationChanges:[]}),options.parentId),this.contextId=options.contextId,this.structureKind=options.structureKind,this.structureId=options.structureId,this.name=options.name,this.label=options.label,this.source=options.source,this.callee=options.callee,this.role=options.role,Object.freeze(this)}toJSON(){return{...super.toJSON(),contextId:this.contextId,structureKind:this.structureKind,status:this.status,...this.structureId!==void 0?{structureId:this.structureId}:{},...this.name!==void 0?{name:this.name}:{},...this.label!==void 0?{label:this.label}:{},...this.source!==void 0?{source:this.source}:{},...this.callee!==void 0?{callee:this.callee}:{},...this.role!==void 0?{role:this.role}:{}}}}export{CallableRecord};
@@ -0,0 +1,13 @@
1
+ import { BaseRecord } from './record.js';
2
+ import { replaceChildren } from './tree/access.js';
3
+ export declare abstract class CompositeRecord<Value> extends BaseRecord<Value> {
4
+ #private;
5
+ get childIds(): readonly string[];
6
+ [replaceChildren](ids: readonly string[]): void;
7
+ toJSON(): {
8
+ childIds: readonly string[];
9
+ id: string;
10
+ parentId?: string;
11
+ value: Value;
12
+ };
13
+ }
@@ -0,0 +1,2 @@
1
+ /*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
2
+ var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});import{BaseRecord}from"./record.js";import{replaceChildren}from"./tree/access.js";class CompositeRecord extends BaseRecord{static{__name(this,"CompositeRecord")}#childIds=Object.freeze([]);get childIds(){return this.#childIds}[replaceChildren](ids){this.requireWritable(),this.#childIds=ids}toJSON(){return{...super.toJSON(),childIds:this.childIds}}}export{CompositeRecord};
@@ -0,0 +1,14 @@
1
+ import { ResourceOffer } from '@weiliang0121/capix-resources';
2
+ import type { InvocationBoundaryValue, RecordMutation } from './data/index.js';
3
+ import type { BaseRecord } from './record.js';
4
+ import type { Recorder } from './recorder.js';
5
+ import { InvocationBoundaryRecordHelper } from './invocation/boundary/helper.js';
6
+ import type { InvocationBoundaryRecord } from './invocation/boundary/record.js';
7
+ import type { RecordingRootRecord } from './root/record.js';
8
+ export interface RecordWriter {
9
+ root(): RecordingRootRecord;
10
+ add<RecordType extends BaseRecord<unknown>>(record: RecordType): RecordType;
11
+ update<RecordType extends BaseRecord<unknown>>(record: RecordType, apply: (record: RecordType) => void, describe?: (record: RecordType) => RecordMutation): void;
12
+ boundary(location: Parameters<typeof InvocationBoundaryRecordHelper.create>[1], type: InvocationBoundaryValue['type']): InvocationBoundaryRecord;
13
+ }
14
+ export declare const RecordWriterResource: ResourceOffer<Recorder, RecordWriter, Recorder, never>;
@@ -0,0 +1,2 @@
1
+ /*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
2
+ var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});import{ResourceOffer}from"@weiliang0121/capix-resources";import{InvocationBoundaryRecordHelper}from"./invocation/boundary/helper.js";import{RecordingRootHelper}from"./root/helper.js";const RecordWriterResource=new ResourceOffer({name:"records.construct",expose:__name((recorder,activity)=>Object.freeze({root(){return activity.runSync("root",{output:__name(record=>({id:record.id,kind:record.kind}),"output")},()=>RecordingRootHelper.create(recorder))},add(record){return activity.runSync("add",{input:__name(()=>({id:record.id,kind:record.kind}),"input"),output:__name(added=>({id:added.id,kind:added.kind}),"output")},()=>recorder.add(record))},update(record,apply,describe){activity.runSync("update",{input:__name(()=>({id:record.id,kind:record.kind}),"input")},()=>recorder.update(record,apply,describe))},boundary(location,type){return activity.runSync("boundary",{input:__name(()=>({callId:location.callId,type}),"input"),output:__name(record=>({id:record.id,callId:record.callId,type}),"output")},()=>InvocationBoundaryRecordHelper.create(recorder,location,type))}}),"expose"),timing:"access",describe:__name(recorder=>({recorderId:recorder.id}),"describe")});export{RecordWriterResource};
@@ -0,0 +1,10 @@
1
+ import { type TranscriptEvent } from '@weiliang0121/capix-transcript';
2
+ import { type MemoryEvent } from '@weiliang0121/capix-memory';
3
+ import type { ResourceFact } from '@weiliang0121/capix-resources';
4
+ import type { RecordWriter } from './construction.js';
5
+ import type { RecordChangeSource } from './source.js';
6
+ import { TranscriptRecord } from './transcript/record.js';
7
+ import { MemoryRecord } from './memory/record.js';
8
+ export declare function transcriptRecord(event: TranscriptEvent, source?: RecordChangeSource): TranscriptRecord;
9
+ export declare function memoryRecord(event: MemoryEvent<unknown>, source?: RecordChangeSource): MemoryRecord;
10
+ export declare function recordContentFact(fact: ResourceFact, source: RecordChangeSource, writer: RecordWriter): void;
@@ -0,0 +1,2 @@
1
+ /*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
2
+ var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});import{TranscriptFacts}from"@weiliang0121/capix-transcript";import{MemoryFacts}from"@weiliang0121/capix-memory";import{TranscriptRecord}from"./transcript/record.js";import{MemoryRecord}from"./memory/record.js";function transcriptRecord(event,source){const change=event.change;return new TranscriptRecord({transcriptId:event.transcriptId,revision:event.revision,occurredAt:event.occurredAt,...source?{source}:{}},change.kind==="messages-appended"?{action:"append",start:change.start,end:change.start+change.messages.length}:{action:"segment",previousStart:change.previousStart,start:change.start,end:change.end})}__name(transcriptRecord,"transcriptRecord");function memoryRecord(event,source){return new MemoryRecord({memoriesId:event.memoriesId,memoryId:event.change.memoryId,sequence:event.sequence,...source?{source}:{}},{action:event.change.action,...event.change.reason!==void 0?{reason:event.change.reason}:{},result:{content:event.change.value.content}})}__name(memoryRecord,"memoryRecord");function recordContentFact(fact,source,writer){if(fact.contextId!==source.contextId)throw new Error("Content fact forwarding context does not match record source");TranscriptFacts.match(fact.fact,event=>{if(event.origin?.contextId!==source.contextId)throw new Error("Transcript fact origin does not match record source");writer.add(transcriptRecord(event,source))})||MemoryFacts.match(fact.fact,event=>{if(event.origin?.contextId!==source.contextId)throw new Error("Memory fact origin does not match record source");writer.add(memoryRecord(event,source))})}__name(recordContentFact,"recordContentFact");export{memoryRecord,recordContentFact,transcriptRecord};
@@ -0,0 +1,9 @@
1
+ export interface RecordingArchive {
2
+ readonly sourceId: string;
3
+ readonly rootIds: readonly string[];
4
+ readonly revision: number;
5
+ readonly state: 'open' | 'sealed' | 'incomplete';
6
+ }
7
+ export type RecordingArchiveOrigin = Omit<RecordingArchive, 'rootIds'>;
8
+ export declare function validateRecordingArchiveOrigin(value: unknown): asserts value is RecordingArchiveOrigin;
9
+ export declare function validateRecordingArchives(value: unknown): asserts value is readonly RecordingArchive[];
@@ -0,0 +1,2 @@
1
+ /*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
2
+ var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});function validateRecordingArchiveOrigin(value){if(!value||typeof value!="object")throw new Error("\u5386\u53F2\u8BB0\u5F55\u6765\u6E90\u683C\u5F0F\u65E0\u6548\u3002");const source=value;if(typeof source.sourceId!="string"||!source.sourceId||!Number.isSafeInteger(source.revision)||source.revision<0||!["open","sealed","incomplete"].includes(source.state))throw new Error("\u5386\u53F2\u8BB0\u5F55\u6765\u6E90\u683C\u5F0F\u65E0\u6548\u3002")}__name(validateRecordingArchiveOrigin,"validateRecordingArchiveOrigin");function validateRecordingArchives(value){if(!Array.isArray(value))throw new Error("\u5386\u53F2\u8BB0\u5F55\u6765\u6E90\u683C\u5F0F\u65E0\u6548\u3002");const sources=new Set,roots=new Set;for(const archive of value){validateRecordingArchiveOrigin(archive);const source=archive;if(sources.has(source.sourceId)||!Array.isArray(source.rootIds)||source.rootIds.some(id=>typeof id!="string"||!id||roots.has(id)))throw new Error("\u5386\u53F2\u8BB0\u5F55\u6765\u6E90\u5F52\u5C5E\u65E0\u6548\u3002");sources.add(source.sourceId);for(const id of source.rootIds){if(roots.has(id))throw new Error("\u5386\u53F2\u8BB0\u5F55\u6765\u6E90\u5F52\u5C5E\u65E0\u6548\u3002");roots.add(id)}}}__name(validateRecordingArchives,"validateRecordingArchives");export{validateRecordingArchiveOrigin,validateRecordingArchives};
@@ -0,0 +1,43 @@
1
+ import type { BaseRecord, ProcessRecord, RelationChangeRecord } from './types.js';
2
+ import type { RuntimeErrorValue, InvocationFailureFact } from '@weiliang0121/capix-contracts';
3
+ export type RecordKind = 'invocation' | 'runtime' | 'runtime-call' | 'execution' | 'operation' | 'attempt' | 'invocation-boundary' | 'transcript' | 'memory' | 'resource' | 'custom';
4
+ export interface RecordEntry {
5
+ readonly kind: RecordKind;
6
+ readonly data: BaseRecord;
7
+ }
8
+ export type RecordMutation = Readonly<{
9
+ kind: 'added';
10
+ entry: RecordEntry;
11
+ parent?: Readonly<{
12
+ id: string;
13
+ childId: string;
14
+ }>;
15
+ }> | Readonly<{
16
+ kind: 'process-appended';
17
+ id: string;
18
+ process: ProcessRecord;
19
+ }> | Readonly<{
20
+ kind: 'relation-appended';
21
+ id: string;
22
+ relation: RelationChangeRecord;
23
+ }> | Readonly<{
24
+ kind: 'finished';
25
+ id: string;
26
+ status: 'succeeded' | 'failed';
27
+ result: Readonly<{
28
+ output?: unknown;
29
+ resultOf?: number;
30
+ error?: RuntimeErrorValue;
31
+ failure?: InvocationFailureFact;
32
+ }>;
33
+ }> | Readonly<{
34
+ kind: 'replaced';
35
+ entry: RecordEntry;
36
+ }>;
37
+ export type RecordChangeEvent = Readonly<{
38
+ type: 'record';
39
+ recorderId: string;
40
+ revision: number;
41
+ occurredAt: string;
42
+ change: RecordMutation;
43
+ }>;
@@ -0,0 +1 @@
1
+ /*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
@@ -0,0 +1,8 @@
1
+ export * from './types.js';
2
+ export * from './invocation.js';
3
+ export * from './memory.js';
4
+ export * from './transcript.js';
5
+ export * from './resource.js';
6
+ export * from './changes.js';
7
+ export * from './archive.js';
8
+ export * from './validate.js';
@@ -0,0 +1,2 @@
1
+ /*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
2
+ export*from"./types.js";export*from"./invocation.js";export*from"./memory.js";export*from"./transcript.js";export*from"./resource.js";export*from"./changes.js";export*from"./archive.js";export*from"./validate.js";
@@ -0,0 +1,10 @@
1
+ import type { InvocationValue, ProcessRecord } from './types.js';
2
+ type OutputProcess = Extract<ProcessRecord, {
3
+ type: 'return';
4
+ output: unknown;
5
+ }>;
6
+ export declare function outputProcess(value: Pick<InvocationValue, 'processes'>, sequence: number, before?: number): OutputProcess;
7
+ export declare function hasOutput(value: InvocationValue): boolean;
8
+ export declare function finalOutputProcess(value: Pick<InvocationValue, 'processes'>, sequence: number): OutputProcess;
9
+ export declare function readOutput<Input, Output>(value: InvocationValue<Input, Output>): Output | undefined;
10
+ export {};
@@ -0,0 +1,2 @@
1
+ /*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
2
+ var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});function outputProcess(value,sequence,before=value.processes.length+1){const process=value.processes[sequence-1];if(!Number.isSafeInteger(sequence)||sequence<1||sequence>=before||!process||process.sequence!==sequence||process.type!=="return"||!Object.hasOwn(process,"output")||Object.hasOwn(process,"resultOf"))throw new Error("Invalid local result reference");return process}__name(outputProcess,"outputProcess");function hasOutput(value){return Object.hasOwn(value,"output")||Object.hasOwn(value,"resultOf")}__name(hasOutput,"hasOutput");function finalOutputProcess(value,sequence){const last=value.processes.at(-1);if(!last||last.type!=="return"||sequence!==("resultOf"in last?last.resultOf:last.sequence))throw new Error("Final result must reference the last returned output");return outputProcess(value,sequence)}__name(finalOutputProcess,"finalOutputProcess");function readOutput(value){if(Object.hasOwn(value,"resultOf")){if(Object.hasOwn(value,"output"))throw new Error("Output and local result reference are mutually exclusive");return finalOutputProcess(value,value.resultOf).output}return value.output}__name(readOutput,"readOutput");export{finalOutputProcess,hasOutput,outputProcess,readOutput};
@@ -0,0 +1,26 @@
1
+ import type { BaseRecord } from './types.js';
2
+ export interface MemoryRecordContent {
3
+ readonly content: string;
4
+ }
5
+ export interface MemoryRecordObservation {
6
+ readonly items: readonly {
7
+ readonly id: string;
8
+ readonly value: MemoryRecordContent;
9
+ readonly records: readonly MemoryRecord[];
10
+ }[];
11
+ }
12
+ export interface MemoryRecordValue {
13
+ readonly action: 'create' | 'update';
14
+ readonly reason?: string;
15
+ readonly result: MemoryRecordContent;
16
+ }
17
+ export interface MemoryRecord extends BaseRecord<MemoryRecordValue> {
18
+ readonly memoryId: string;
19
+ readonly memoriesId: string;
20
+ readonly sequence: number;
21
+ readonly contextId?: string;
22
+ readonly callId?: string;
23
+ readonly executionId?: string;
24
+ readonly operationId?: string;
25
+ }
26
+ export declare function validateMemoryRecordValue(value: unknown): asserts value is MemoryRecordValue;
@@ -0,0 +1,2 @@
1
+ /*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
2
+ var __defProp=Object.defineProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:!0});function validateMemoryRecordValue(value){if(!value||typeof value!="object"||Array.isArray(value))throw new Error("Invalid memory record value");const record=value;if(!Object.hasOwn(record,"action")||!Object.hasOwn(record,"result")||record.action!=="create"&&record.action!=="update"||Object.keys(record).some(key=>!["action","reason","result"].includes(key))||Object.hasOwn(record,"reason")&&typeof record.reason!="string")throw new Error("Invalid memory record value");const result=record.result;if(!result||typeof result!="object"||Array.isArray(result)||Object.keys(result).length!==1||!Object.hasOwn(result,"content")||typeof result.content!="string")throw new Error("Invalid memory display value")}__name(validateMemoryRecordValue,"validateMemoryRecordValue");export{validateMemoryRecordValue};
@@ -0,0 +1,10 @@
1
+ import type { BaseRecord } from './types.js';
2
+ export interface ResourceRecord<Detail = unknown> extends BaseRecord<Detail> {
3
+ readonly parentId: string;
4
+ readonly access: string;
5
+ readonly supplyId: string;
6
+ readonly sequence: number;
7
+ readonly occurredAt: string;
8
+ readonly phase: 'bound' | 'available' | 'unavailable' | 'started' | 'returned' | 'threw';
9
+ readonly interactionId?: string;
10
+ }
@@ -0,0 +1 @@
1
+ /*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
@@ -0,0 +1,19 @@
1
+ import type { BaseRecord } from './types.js';
2
+ export type TranscriptChange = {
3
+ readonly action: 'append';
4
+ readonly start: number;
5
+ readonly end: number;
6
+ } | {
7
+ readonly action: 'segment';
8
+ readonly previousStart: number;
9
+ readonly start: number;
10
+ readonly end: number;
11
+ };
12
+ export interface TranscriptRecord extends BaseRecord<TranscriptChange> {
13
+ readonly transcriptId: string;
14
+ readonly revision: number;
15
+ readonly occurredAt: string;
16
+ readonly contextId?: string;
17
+ readonly callId?: string;
18
+ readonly executionId?: string;
19
+ }
@@ -0,0 +1 @@
1
+ /*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
@@ -0,0 +1,189 @@
1
+ import type { RecordingArchiveOrigin } from './archive.js';
2
+ import type { InvocationFailureFact, RuntimeErrorValue } from '@weiliang0121/capix-contracts';
3
+ import type { CallableKind } from '@weiliang0121/capix-contracts';
4
+ import type { TranscriptRecord } from './transcript.js';
5
+ import type { MemoryRecord } from './memory.js';
6
+ import type { ResourceRecord } from './resource.js';
7
+ import type { InvocationRelationIdentity } from '@weiliang0121/capix-contracts';
8
+ export interface BaseRecord<Value = unknown> {
9
+ readonly id: string;
10
+ readonly parentId?: string;
11
+ readonly value: Value;
12
+ }
13
+ export interface CompositeRecord<Value = unknown> extends BaseRecord<Value> {
14
+ readonly childIds: readonly string[];
15
+ }
16
+ export interface RecordingRootValue {
17
+ readonly createdAt: string;
18
+ }
19
+ export interface RecordingRootRecord extends CompositeRecord<RecordingRootValue> {
20
+ }
21
+ export type ProcessRecord = Readonly<{
22
+ sequence: number;
23
+ eventSequence: number;
24
+ round: number;
25
+ occurredAt: string;
26
+ offsetMs: number;
27
+ } & ({
28
+ stage: 'execute';
29
+ type: 'start';
30
+ input: unknown;
31
+ } | {
32
+ stage: 'execute' | 'receive' | 'handling';
33
+ type: 'return';
34
+ output: unknown;
35
+ } | {
36
+ stage: 'receive';
37
+ type: 'return';
38
+ resultOf: number;
39
+ } | {
40
+ stage: 'execute' | 'receive' | 'handling';
41
+ type: 'throw';
42
+ error: RuntimeErrorValue;
43
+ failure?: InvocationFailureFact;
44
+ } | {
45
+ stage: 'receive' | 'handling';
46
+ type: 'continue';
47
+ input: unknown;
48
+ reason: string;
49
+ } | {
50
+ stage: 'handling';
51
+ type: 'start' | 'unhandled';
52
+ error: RuntimeErrorValue;
53
+ failure?: InvocationFailureFact;
54
+ } | {
55
+ stage: 'control';
56
+ type: 'stop';
57
+ error: RuntimeErrorValue;
58
+ failure?: InvocationFailureFact;
59
+ })>;
60
+ export type RecordedInvocationResult = Readonly<{
61
+ status: 'succeeded';
62
+ output: unknown;
63
+ } | {
64
+ status: 'failed';
65
+ error: RuntimeErrorValue;
66
+ failure?: InvocationFailureFact;
67
+ }>;
68
+ export type RecordedRelationChange = Readonly<{
69
+ kind: 'attached';
70
+ } | {
71
+ kind: 'returned';
72
+ result: RecordedInvocationResult;
73
+ } | {
74
+ kind: 'receiving';
75
+ } | {
76
+ kind: 'accepted';
77
+ output: unknown;
78
+ } | {
79
+ kind: 'handled';
80
+ output: unknown;
81
+ } | {
82
+ kind: 'failed';
83
+ source: 'work' | 'observation';
84
+ error: RuntimeErrorValue;
85
+ failure?: InvocationFailureFact;
86
+ }>;
87
+ export interface RelationChangeRecord {
88
+ readonly identity: InvocationRelationIdentity;
89
+ readonly eventSequence: number;
90
+ readonly occurredAt: string;
91
+ readonly offsetMs: number;
92
+ readonly childId?: string;
93
+ readonly change: RecordedRelationChange;
94
+ }
95
+ export interface InvocationValue<Input = unknown, Output = unknown> {
96
+ readonly processes: readonly ProcessRecord[];
97
+ readonly relationChanges: readonly RelationChangeRecord[];
98
+ input: Input;
99
+ output?: Output;
100
+ resultOf?: number;
101
+ error?: RuntimeErrorValue;
102
+ failure?: InvocationFailureFact;
103
+ }
104
+ export interface RuntimeCallValue<Input = unknown, Output = unknown> extends InvocationValue<Input, Output> {
105
+ readonly startedAt: string;
106
+ }
107
+ export interface RuntimeCallRecord<Input = unknown, Output = unknown> extends CompositeRecord<RuntimeCallValue<Input, Output>> {
108
+ readonly contextId: string;
109
+ readonly runtimeInstanceId: string;
110
+ readonly status: 'running' | 'succeeded' | 'failed';
111
+ }
112
+ export interface ExecutionValue<Input = unknown, Output = unknown> extends InvocationValue<Input, Output> {
113
+ startedAt: string;
114
+ }
115
+ export interface ExecutionRecord<Input = unknown, Output = unknown> extends CompositeRecord<ExecutionValue<Input, Output>> {
116
+ readonly contextId: string;
117
+ readonly status: 'running' | 'succeeded' | 'failed';
118
+ }
119
+ export interface OperationRecord<Input = unknown, Output = unknown> extends CompositeRecord<InvocationValue<Input, Output>> {
120
+ readonly contextId: string;
121
+ readonly status: 'running' | 'succeeded' | 'failed';
122
+ readonly executionId: string;
123
+ readonly operationInstanceId: string;
124
+ readonly parentOperationId?: string;
125
+ readonly operation: string;
126
+ readonly label: string;
127
+ readonly source: string;
128
+ readonly caller: string;
129
+ readonly callee: string;
130
+ }
131
+ export interface AttemptValue<Input = unknown, Output = unknown> extends InvocationValue<Input, Output> {
132
+ }
133
+ export interface AttemptRecord<Input = unknown, Output = unknown> extends CompositeRecord<AttemptValue<Input, Output>> {
134
+ readonly contextId: string;
135
+ readonly status: 'running' | 'succeeded' | 'failed';
136
+ readonly operationId: string;
137
+ readonly name: string;
138
+ readonly label: string;
139
+ readonly source: string;
140
+ readonly caller: string;
141
+ readonly callee: string;
142
+ }
143
+ export interface InvocationBoundaryValue {
144
+ readonly type: 'call' | 'return' | 'throw';
145
+ readonly scope: 'work';
146
+ }
147
+ export interface InvocationBoundaryRecord extends BaseRecord<InvocationBoundaryValue> {
148
+ readonly scopeId: string;
149
+ readonly executionId?: string;
150
+ readonly callId: string;
151
+ readonly sequence: number;
152
+ readonly occurredAt: string;
153
+ readonly offsetMs: number;
154
+ }
155
+ export interface LegacyExecutionRecordSnapshot {
156
+ readonly archive?: RecordingArchiveOrigin;
157
+ runtimeCall: RuntimeCallRecord;
158
+ runtimeEvents: InvocationBoundaryRecord[];
159
+ execution: ExecutionRecord;
160
+ operations: OperationRecord[];
161
+ attempts: AttemptRecord[];
162
+ events: InvocationBoundaryRecord[];
163
+ resources: ResourceRecord[];
164
+ }
165
+ export interface CallableValue<Input = unknown, Output = unknown> extends InvocationValue<Input, Output> {
166
+ readonly startedAt?: string;
167
+ }
168
+ export interface CallableRecord<Input = unknown, Output = unknown> extends CompositeRecord<CallableValue<Input, Output>> {
169
+ readonly contextId: string;
170
+ readonly structureKind: CallableKind;
171
+ readonly structureId?: string;
172
+ readonly name?: string;
173
+ readonly label?: string;
174
+ readonly source?: string;
175
+ readonly callee?: string;
176
+ readonly role?: string;
177
+ readonly status: 'running' | 'succeeded' | 'failed';
178
+ }
179
+ export interface ExecutionRecordSnapshot {
180
+ readonly archive?: RecordingArchiveOrigin;
181
+ readonly execution: CallableRecord;
182
+ readonly calls: readonly CallableRecord[];
183
+ readonly rootCall?: CallableRecord;
184
+ readonly ancestors?: readonly CallableRecord[];
185
+ readonly boundaries: readonly InvocationBoundaryRecord[];
186
+ readonly transcripts: readonly TranscriptRecord[];
187
+ readonly memories: readonly MemoryRecord[];
188
+ readonly resources: readonly ResourceRecord[];
189
+ }
@@ -0,0 +1 @@
1
+ /*! MIT License | Copyright (c) 2026 wei.liang | See LICENSE */
@@ -0,0 +1,4 @@
1
+ import type { ExecutionRecordSnapshot, LegacyExecutionRecordSnapshot, InvocationValue } from './types.js';
2
+ export declare function validateExecutionRecordSnapshot(value: unknown): asserts value is ExecutionRecordSnapshot;
3
+ export declare function validateLegacyExecutionRecordSnapshot(value: unknown): asserts value is LegacyExecutionRecordSnapshot;
4
+ export declare function validateInvocationRecordValue(value: unknown, ownerContextId: string): asserts value is InvocationValue;