@rasensio/aidlc 1.2.1 → 1.4.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 (120) hide show
  1. package/dist/cli.js +4 -0
  2. package/dist/cli.js.map +1 -1
  3. package/dist/commands/claim.d.ts +15 -0
  4. package/dist/commands/claim.d.ts.map +1 -0
  5. package/dist/commands/claim.js +122 -0
  6. package/dist/commands/claim.js.map +1 -0
  7. package/dist/commands/cost.d.ts +12 -0
  8. package/dist/commands/cost.d.ts.map +1 -0
  9. package/dist/commands/cost.js +409 -0
  10. package/dist/commands/cost.js.map +1 -0
  11. package/dist/commands/gate.d.ts.map +1 -1
  12. package/dist/commands/gate.js +17 -0
  13. package/dist/commands/gate.js.map +1 -1
  14. package/dist/commands/init.d.ts.map +1 -1
  15. package/dist/commands/init.js +38 -2
  16. package/dist/commands/init.js.map +1 -1
  17. package/dist/commands/status.d.ts.map +1 -1
  18. package/dist/commands/status.js +59 -2
  19. package/dist/commands/status.js.map +1 -1
  20. package/dist/commands/transition.d.ts.map +1 -1
  21. package/dist/commands/transition.js +30 -0
  22. package/dist/commands/transition.js.map +1 -1
  23. package/dist/core/gate.d.ts +7 -0
  24. package/dist/core/gate.d.ts.map +1 -1
  25. package/dist/core/gate.js.map +1 -1
  26. package/dist/core/types.d.ts +18 -1
  27. package/dist/core/types.d.ts.map +1 -1
  28. package/dist/cost/config.d.ts +8 -0
  29. package/dist/cost/config.d.ts.map +1 -0
  30. package/dist/cost/config.js +37 -0
  31. package/dist/cost/config.js.map +1 -0
  32. package/dist/cost/hooks/claude-code.d.ts +29 -0
  33. package/dist/cost/hooks/claude-code.d.ts.map +1 -0
  34. package/dist/cost/hooks/claude-code.js +101 -0
  35. package/dist/cost/hooks/claude-code.js.map +1 -0
  36. package/dist/cost/hooks/kiro.d.ts +17 -0
  37. package/dist/cost/hooks/kiro.d.ts.map +1 -0
  38. package/dist/cost/hooks/kiro.js +66 -0
  39. package/dist/cost/hooks/kiro.js.map +1 -0
  40. package/dist/cost/ledger.d.ts +70 -0
  41. package/dist/cost/ledger.d.ts.map +1 -0
  42. package/dist/cost/ledger.js +314 -0
  43. package/dist/cost/ledger.js.map +1 -0
  44. package/dist/cost/providers/claude-code.d.ts +20 -0
  45. package/dist/cost/providers/claude-code.d.ts.map +1 -0
  46. package/dist/cost/providers/claude-code.js +116 -0
  47. package/dist/cost/providers/claude-code.js.map +1 -0
  48. package/dist/cost/providers/kiro.d.ts +19 -0
  49. package/dist/cost/providers/kiro.d.ts.map +1 -0
  50. package/dist/cost/providers/kiro.js +147 -0
  51. package/dist/cost/providers/kiro.js.map +1 -0
  52. package/dist/cost/providers/provider.d.ts +36 -0
  53. package/dist/cost/providers/provider.d.ts.map +1 -0
  54. package/dist/cost/providers/provider.js +21 -0
  55. package/dist/cost/providers/provider.js.map +1 -0
  56. package/dist/cost/rates-bundled.d.ts +11 -0
  57. package/dist/cost/rates-bundled.d.ts.map +1 -0
  58. package/dist/cost/rates-bundled.js +23 -0
  59. package/dist/cost/rates-bundled.js.map +1 -0
  60. package/dist/cost/rates.d.ts +42 -0
  61. package/dist/cost/rates.d.ts.map +1 -0
  62. package/dist/cost/rates.js +190 -0
  63. package/dist/cost/rates.js.map +1 -0
  64. package/dist/cost/recorder.d.ts +57 -0
  65. package/dist/cost/recorder.d.ts.map +1 -0
  66. package/dist/cost/recorder.js +339 -0
  67. package/dist/cost/recorder.js.map +1 -0
  68. package/dist/cost/report.d.ts +44 -0
  69. package/dist/cost/report.d.ts.map +1 -0
  70. package/dist/cost/report.js +164 -0
  71. package/dist/cost/report.js.map +1 -0
  72. package/dist/cost/sessions.d.ts +40 -0
  73. package/dist/cost/sessions.d.ts.map +1 -0
  74. package/dist/cost/sessions.js +200 -0
  75. package/dist/cost/sessions.js.map +1 -0
  76. package/dist/cost/sync.d.ts +24 -0
  77. package/dist/cost/sync.d.ts.map +1 -0
  78. package/dist/cost/sync.js +191 -0
  79. package/dist/cost/sync.js.map +1 -0
  80. package/dist/cost/types.d.ts +116 -0
  81. package/dist/cost/types.d.ts.map +1 -0
  82. package/dist/cost/types.js +13 -0
  83. package/dist/cost/types.js.map +1 -0
  84. package/dist/setup/setup-compute.d.ts +6 -0
  85. package/dist/setup/setup-compute.d.ts.map +1 -1
  86. package/dist/setup/setup-compute.js +3 -0
  87. package/dist/setup/setup-compute.js.map +1 -1
  88. package/dist/traceability/cache.d.ts +21 -0
  89. package/dist/traceability/cache.d.ts.map +1 -0
  90. package/dist/traceability/cache.js +106 -0
  91. package/dist/traceability/cache.js.map +1 -0
  92. package/dist/traceability/coverage-block.d.ts +21 -0
  93. package/dist/traceability/coverage-block.d.ts.map +1 -0
  94. package/dist/traceability/coverage-block.js +41 -0
  95. package/dist/traceability/coverage-block.js.map +1 -0
  96. package/dist/traceability/gate-criterion.d.ts +34 -0
  97. package/dist/traceability/gate-criterion.d.ts.map +1 -0
  98. package/dist/traceability/gate-criterion.js +128 -0
  99. package/dist/traceability/gate-criterion.js.map +1 -0
  100. package/dist/traceability/matrix.d.ts +35 -0
  101. package/dist/traceability/matrix.d.ts.map +1 -0
  102. package/dist/traceability/matrix.js +93 -0
  103. package/dist/traceability/matrix.js.map +1 -0
  104. package/dist/traceability/parser.d.ts +27 -0
  105. package/dist/traceability/parser.d.ts.map +1 -0
  106. package/dist/traceability/parser.js +101 -0
  107. package/dist/traceability/parser.js.map +1 -0
  108. package/dist/traceability/scanner.d.ts +62 -0
  109. package/dist/traceability/scanner.d.ts.map +1 -0
  110. package/dist/traceability/scanner.js +198 -0
  111. package/dist/traceability/scanner.js.map +1 -0
  112. package/dist/traceability/types.d.ts +77 -0
  113. package/dist/traceability/types.d.ts.map +1 -0
  114. package/dist/traceability/types.js +8 -0
  115. package/dist/traceability/types.js.map +1 -0
  116. package/package.json +3 -5
  117. package/dist/commands/setup.d.ts +0 -24
  118. package/dist/commands/setup.d.ts.map +0 -1
  119. package/dist/commands/setup.js +0 -262
  120. package/dist/commands/setup.js.map +0 -1
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Cost reports: per-instance, all-instances, by-template, unattributed.
3
+ *
4
+ * Reads ledgers only — never re-parses platform records (FR7.4). Applies
5
+ * read-time fidelity precedence, then prices weighted usage against the
6
+ * effective rate table. Every dollar-bearing report names its snapshot.
7
+ *
8
+ * Design: design.md §4.5
9
+ */
10
+ import type { CostConfig, CostFidelity, CostEntry } from './types.js';
11
+ export interface PhaseCost {
12
+ phase: string;
13
+ microUsd: number | null;
14
+ unpricedModels: string[];
15
+ tokens: number;
16
+ credits: number;
17
+ elapsedSeconds: number;
18
+ }
19
+ export interface InstanceCost {
20
+ instance: string;
21
+ template: string | null;
22
+ microUsd: number | null;
23
+ unpricedModels: string[];
24
+ tokens: number;
25
+ credits: number;
26
+ elapsedSeconds: number;
27
+ fidelityMix: Record<CostFidelity, number>;
28
+ phases: PhaseCost[];
29
+ snapshot: string;
30
+ }
31
+ /** Compute the full cost view of one instance. */
32
+ export declare function instanceCost(projectRoot: string, instance: string, config: CostConfig | null): InstanceCost;
33
+ /** All instances with state directories. */
34
+ export declare function listInstances(projectRoot: string): string[];
35
+ export interface TemplateRollup {
36
+ template: string;
37
+ count: number;
38
+ avgMicroUsd: number;
39
+ avgElapsedSeconds: number;
40
+ }
41
+ export declare function byTemplate(projectRoot: string, config: CostConfig | null): TemplateRollup[];
42
+ /** Unattributed ledger entries (FR7.2 --unattributed). */
43
+ export declare function unattributedEntries(projectRoot: string): CostEntry[];
44
+ //# sourceMappingURL=report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/cost/report.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEtE,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IAC1C,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AA6DD,kDAAkD;AAClD,wBAAgB,YAAY,CAC1B,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,UAAU,GAAG,IAAI,GACxB,YAAY,CA8Dd;AAED,4CAA4C;AAC5C,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAO3D;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAgB,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,GAAG,cAAc,EAAE,CAoB3F;AAED,0DAA0D;AAC1D,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,EAAE,CAEpE"}
@@ -0,0 +1,164 @@
1
+ /**
2
+ * Cost reports: per-instance, all-instances, by-template, unattributed.
3
+ *
4
+ * Reads ledgers only — never re-parses platform records (FR7.4). Applies
5
+ * read-time fidelity precedence, then prices weighted usage against the
6
+ * effective rate table. Every dollar-bearing report names its snapshot.
7
+ *
8
+ * Design: design.md §4.5
9
+ */
10
+ import { existsSync, readdirSync } from 'node:fs';
11
+ import { join } from 'node:path';
12
+ import { loadYaml } from '../state/yaml-helpers.js';
13
+ import { readEntries, applyPrecedence, ledgerPath, unattributedPath } from './ledger.js';
14
+ import { priceUnits, effectiveRates } from './rates.js';
15
+ function sumWeighted(weighted, rates) {
16
+ let micro = 0;
17
+ let anyPriced = false;
18
+ const unpriced = new Set();
19
+ let tokens = 0;
20
+ let credits = 0;
21
+ for (const { entry, weight } of weighted) {
22
+ if (weight === 0 || entry.units === null)
23
+ continue;
24
+ const price = priceUnits(entry.units, rates);
25
+ if (price === null) {
26
+ unpriced.add(entry.units.kind === 'tokens' ? entry.units.model : 'kiro-credit');
27
+ }
28
+ else {
29
+ micro += price * weight;
30
+ anyPriced = true;
31
+ }
32
+ if (entry.units.kind === 'tokens') {
33
+ tokens += (entry.units.input_tokens + entry.units.output_tokens) * weight;
34
+ }
35
+ else {
36
+ credits += entry.units.credits * weight;
37
+ }
38
+ }
39
+ return { microUsd: anyPriced || unpriced.size === 0 ? Math.round(micro) : null, unpriced, tokens, credits };
40
+ }
41
+ function phaseElapsed(projectRoot, instance) {
42
+ const dir = join(projectRoot, '.aidlc', 'state', instance);
43
+ const out = new Map();
44
+ if (!existsSync(dir))
45
+ return out;
46
+ for (const f of readdirSync(dir)) {
47
+ if (!f.startsWith('phase-') || !f.endsWith('.yaml'))
48
+ continue;
49
+ try {
50
+ const state = loadYaml(join(dir, f));
51
+ out.set(state.phase, state.metrics?.elapsed_seconds ?? 0);
52
+ }
53
+ catch {
54
+ continue;
55
+ }
56
+ }
57
+ return out;
58
+ }
59
+ function instanceTemplate(projectRoot, instance) {
60
+ try {
61
+ const meta = loadYaml(join(projectRoot, '.aidlc', 'state', instance, 'instance.yaml'));
62
+ return meta.template ?? null;
63
+ }
64
+ catch {
65
+ return null;
66
+ }
67
+ }
68
+ /** Compute the full cost view of one instance. */
69
+ export function instanceCost(projectRoot, instance, config) {
70
+ const rates = effectiveRates(projectRoot, config);
71
+ const entries = readEntries(ledgerPath(projectRoot, instance));
72
+ const weighted = applyPrecedence(entries);
73
+ const elapsed = phaseElapsed(projectRoot, instance);
74
+ const byPhase = new Map();
75
+ for (const w of weighted) {
76
+ const phase = w.entry.phase ?? 'unknown';
77
+ const list = byPhase.get(phase) ?? [];
78
+ list.push(w);
79
+ byPhase.set(phase, list);
80
+ }
81
+ const phases = [];
82
+ for (const [phase, list] of byPhase) {
83
+ const s = sumWeighted(list, rates);
84
+ phases.push({
85
+ phase,
86
+ microUsd: s.microUsd,
87
+ unpricedModels: [...s.unpriced],
88
+ tokens: Math.round(s.tokens),
89
+ credits: s.credits,
90
+ elapsedSeconds: elapsed.get(phase) ?? 0,
91
+ });
92
+ }
93
+ // Phases with time but no cost still appear.
94
+ for (const [phase, secs] of elapsed) {
95
+ if (secs > 0 && !byPhase.has(phase)) {
96
+ phases.push({ phase, microUsd: 0, unpricedModels: [], tokens: 0, credits: 0, elapsedSeconds: secs });
97
+ }
98
+ }
99
+ const total = sumWeighted(weighted, rates);
100
+ const fidelityMix = { metered: 0, reconciled: 0, estimated: 0, unknown: 0 };
101
+ let mixTotal = 0;
102
+ for (const { entry, weight } of weighted) {
103
+ if (entry.units === null)
104
+ continue;
105
+ fidelityMix[entry.fidelity] += weight;
106
+ mixTotal += weight;
107
+ }
108
+ if (mixTotal > 0) {
109
+ for (const k of Object.keys(fidelityMix)) {
110
+ fidelityMix[k] = fidelityMix[k] / mixTotal;
111
+ }
112
+ }
113
+ let totalElapsed = 0;
114
+ for (const secs of elapsed.values())
115
+ totalElapsed += secs;
116
+ return {
117
+ instance,
118
+ template: instanceTemplate(projectRoot, instance),
119
+ microUsd: total.microUsd,
120
+ unpricedModels: [...total.unpriced],
121
+ tokens: Math.round(total.tokens),
122
+ credits: total.credits,
123
+ elapsedSeconds: totalElapsed,
124
+ fidelityMix,
125
+ phases,
126
+ snapshot: rates.snapshot,
127
+ };
128
+ }
129
+ /** All instances with state directories. */
130
+ export function listInstances(projectRoot) {
131
+ const dir = join(projectRoot, '.aidlc', 'state');
132
+ if (!existsSync(dir))
133
+ return [];
134
+ return readdirSync(dir, { withFileTypes: true })
135
+ .filter((d) => d.isDirectory())
136
+ .map((d) => d.name)
137
+ .sort();
138
+ }
139
+ export function byTemplate(projectRoot, config) {
140
+ const groups = new Map();
141
+ for (const name of listInstances(projectRoot)) {
142
+ const cost = instanceCost(projectRoot, name, config);
143
+ const template = cost.template ?? '(unknown)';
144
+ const g = groups.get(template) ?? { micro: [], secs: [] };
145
+ g.micro.push(cost.microUsd ?? 0);
146
+ g.secs.push(cost.elapsedSeconds);
147
+ groups.set(template, g);
148
+ }
149
+ const out = [];
150
+ for (const [template, g] of groups) {
151
+ out.push({
152
+ template,
153
+ count: g.micro.length,
154
+ avgMicroUsd: Math.round(g.micro.reduce((a, b) => a + b, 0) / g.micro.length),
155
+ avgElapsedSeconds: Math.round(g.secs.reduce((a, b) => a + b, 0) / g.secs.length),
156
+ });
157
+ }
158
+ return out.sort((a, b) => a.template.localeCompare(b.template));
159
+ }
160
+ /** Unattributed ledger entries (FR7.2 --unattributed). */
161
+ export function unattributedEntries(projectRoot) {
162
+ return readEntries(unattributedPath(projectRoot));
163
+ }
164
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/cost/report.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Session ledger: durable session↔instance mapping (FR1).
3
+ *
4
+ * sessions.ndjson is append-only; the instance.yaml claim field remains
5
+ * concurrency control only. Attribution intervals are derived here.
6
+ *
7
+ * The active-session stash (design §2.3) joins platform session ids to
8
+ * claims: SessionStart hooks write stash entries; `aidlc claim` resolves
9
+ * the current session with a strict single-candidate rule.
10
+ *
11
+ * Design: design.md §2.2, §2.3, §4.3
12
+ */
13
+ import type { SessionEvent, ClaimInterval, ActiveSession } from './types.js';
14
+ export declare function sessionsPath(projectRoot: string, instance: string): string;
15
+ export declare function stashDir(projectRoot: string): string;
16
+ /** Append a session event (O_APPEND whole-line write). */
17
+ export declare function appendSessionEvent(path: string, event: SessionEvent): void;
18
+ /** Read valid session events; missing file → empty; bad lines skipped. */
19
+ export declare function readSessionEvents(path: string): SessionEvent[];
20
+ /**
21
+ * Resolve attribution intervals from session events (FR1.3).
22
+ *
23
+ * claim → release pairs per session; an unreleased claim is bounded by
24
+ * min(now, lastEventForSession + claimTimeoutMinutes) and marked open.
25
+ * Renew events extend the liveness bound of an open claim.
26
+ */
27
+ export declare function resolveIntervals(events: SessionEvent[], claimTimeoutMinutes: number, now?: Date): ClaimInterval[];
28
+ /** Write a stash entry for a just-started platform session. */
29
+ export declare function stashSession(projectRoot: string, session: ActiveSession): void;
30
+ /** Remove stash entries older than the TTL. Called opportunistically. */
31
+ export declare function pruneStash(projectRoot: string, now?: Date): void;
32
+ /** Resolve a directory to its repo identity (git common dir), or null. */
33
+ export declare function repoIdentity(cwd: string): string | null;
34
+ /**
35
+ * Find the current platform session with the strict single-candidate rule:
36
+ * exactly one live stash entry whose repo identity matches → that session;
37
+ * zero or multiple → null (caller degrades to id_source: agent).
38
+ */
39
+ export declare function resolveCurrentSession(projectRoot: string, now?: Date): ActiveSession | null;
40
+ //# sourceMappingURL=sessions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../src/cost/sessions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAgBH,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAM7E,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE1E;AAED,wBAAgB,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAEpD;AAgBD,0DAA0D;AAC1D,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,IAAI,CAS1E;AAED,0EAA0E;AAC1E,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,EAAE,CAuB9D;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,YAAY,EAAE,EACtB,mBAAmB,EAAE,MAAM,EAC3B,GAAG,GAAE,IAAiB,GACrB,aAAa,EAAE,CA6BjB;AAiBD,+DAA+D;AAC/D,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,IAAI,CAK9E;AAED,yEAAyE;AACzE,wBAAgB,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,GAAE,IAAiB,GAAG,IAAI,CAc5E;AAED,0EAA0E;AAC1E,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAWvD;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,MAAM,EACnB,GAAG,GAAE,IAAiB,GACrB,aAAa,GAAG,IAAI,CAqBtB"}
@@ -0,0 +1,200 @@
1
+ /**
2
+ * Session ledger: durable session↔instance mapping (FR1).
3
+ *
4
+ * sessions.ndjson is append-only; the instance.yaml claim field remains
5
+ * concurrency control only. Attribution intervals are derived here.
6
+ *
7
+ * The active-session stash (design §2.3) joins platform session ids to
8
+ * claims: SessionStart hooks write stash entries; `aidlc claim` resolves
9
+ * the current session with a strict single-candidate rule.
10
+ *
11
+ * Design: design.md §2.2, §2.3, §4.3
12
+ */
13
+ import { readFileSync, writeFileSync, readdirSync, unlinkSync, openSync, writeSync, closeSync, constants, mkdirSync, existsSync, } from 'node:fs';
14
+ import { dirname, join } from 'node:path';
15
+ import { execFileSync } from 'node:child_process';
16
+ import { SESSION_ID_RE } from './types.js';
17
+ const EVENTS = new Set(['claim', 'renew', 'release']);
18
+ const STASH_TTL_MS = 48 * 60 * 60 * 1000;
19
+ export function sessionsPath(projectRoot, instance) {
20
+ return join(projectRoot, '.aidlc', 'state', instance, 'sessions.ndjson');
21
+ }
22
+ export function stashDir(projectRoot) {
23
+ return join(projectRoot, '.aidlc', 'cost', 'active-sessions');
24
+ }
25
+ function isValidEvent(e) {
26
+ if (typeof e !== 'object' || e === null)
27
+ return false;
28
+ const r = e;
29
+ return (EVENTS.has(r.event) &&
30
+ typeof r.session_id === 'string' &&
31
+ SESSION_ID_RE.test(r.session_id) &&
32
+ (r.id_source === 'platform' || r.id_source === 'agent') &&
33
+ typeof r.agent === 'string' &&
34
+ typeof r.timestamp === 'string' &&
35
+ !Number.isNaN(Date.parse(r.timestamp)));
36
+ }
37
+ /** Append a session event (O_APPEND whole-line write). */
38
+ export function appendSessionEvent(path, event) {
39
+ if (!isValidEvent(event))
40
+ throw new Error('invalid session event');
41
+ mkdirSync(dirname(path), { recursive: true });
42
+ const fd = openSync(path, constants.O_WRONLY | constants.O_APPEND | constants.O_CREAT);
43
+ try {
44
+ writeSync(fd, JSON.stringify(event) + '\n');
45
+ }
46
+ finally {
47
+ closeSync(fd);
48
+ }
49
+ }
50
+ /** Read valid session events; missing file → empty; bad lines skipped. */
51
+ export function readSessionEvents(path) {
52
+ let raw;
53
+ try {
54
+ raw = readFileSync(path, 'utf8');
55
+ }
56
+ catch (err) {
57
+ if (err.code === 'ENOENT')
58
+ return [];
59
+ throw err;
60
+ }
61
+ const events = [];
62
+ let skipped = 0;
63
+ for (const line of raw.split('\n')) {
64
+ const t = line.trim();
65
+ if (t === '')
66
+ continue;
67
+ try {
68
+ const parsed = JSON.parse(t);
69
+ if (isValidEvent(parsed))
70
+ events.push(parsed);
71
+ else
72
+ skipped++;
73
+ }
74
+ catch {
75
+ skipped++;
76
+ }
77
+ }
78
+ if (skipped > 0)
79
+ process.stderr.write(`${path}: skipped ${skipped} invalid line(s)\n`);
80
+ return events;
81
+ }
82
+ /**
83
+ * Resolve attribution intervals from session events (FR1.3).
84
+ *
85
+ * claim → release pairs per session; an unreleased claim is bounded by
86
+ * min(now, lastEventForSession + claimTimeoutMinutes) and marked open.
87
+ * Renew events extend the liveness bound of an open claim.
88
+ */
89
+ export function resolveIntervals(events, claimTimeoutMinutes, now = new Date()) {
90
+ const intervals = [];
91
+ const open = new Map();
92
+ for (const e of events) {
93
+ const cur = open.get(e.session_id);
94
+ if (e.event === 'claim') {
95
+ // A re-claim without release closes the previous interval at the new claim.
96
+ if (cur) {
97
+ intervals.push(closedInterval(cur.claim, e.timestamp, false));
98
+ }
99
+ open.set(e.session_id, { claim: e, lastSeen: e.timestamp });
100
+ }
101
+ else if (e.event === 'renew' && cur) {
102
+ cur.lastSeen = e.timestamp;
103
+ }
104
+ else if (e.event === 'release' && cur) {
105
+ intervals.push(closedInterval(cur.claim, e.timestamp, false));
106
+ open.delete(e.session_id);
107
+ }
108
+ }
109
+ for (const { claim, lastSeen } of open.values()) {
110
+ const bound = Math.min(now.getTime(), Date.parse(lastSeen) + claimTimeoutMinutes * 60_000);
111
+ intervals.push(closedInterval(claim, new Date(bound).toISOString(), true));
112
+ }
113
+ return intervals;
114
+ }
115
+ function closedInterval(claim, to, open) {
116
+ return {
117
+ session_id: claim.session_id,
118
+ id_source: claim.id_source,
119
+ agent: claim.agent,
120
+ from: claim.timestamp,
121
+ to,
122
+ open,
123
+ };
124
+ }
125
+ // ---------------------------------------------------------------------------
126
+ // Active-session stash (design §2.3)
127
+ // ---------------------------------------------------------------------------
128
+ /** Write a stash entry for a just-started platform session. */
129
+ export function stashSession(projectRoot, session) {
130
+ if (!SESSION_ID_RE.test(session.session_id))
131
+ throw new Error('invalid session id');
132
+ const dir = stashDir(projectRoot);
133
+ mkdirSync(dir, { recursive: true });
134
+ writeFileSync(join(dir, `${session.session_id}.json`), JSON.stringify(session) + '\n');
135
+ }
136
+ /** Remove stash entries older than the TTL. Called opportunistically. */
137
+ export function pruneStash(projectRoot, now = new Date()) {
138
+ const dir = stashDir(projectRoot);
139
+ if (!existsSync(dir))
140
+ return;
141
+ for (const f of readdirSync(dir)) {
142
+ if (!f.endsWith('.json'))
143
+ continue;
144
+ try {
145
+ const entry = JSON.parse(readFileSync(join(dir, f), 'utf8'));
146
+ if (now.getTime() - Date.parse(entry.started_at) > STASH_TTL_MS) {
147
+ unlinkSync(join(dir, f));
148
+ }
149
+ }
150
+ catch {
151
+ unlinkSync(join(dir, f));
152
+ }
153
+ }
154
+ }
155
+ /** Resolve a directory to its repo identity (git common dir), or null. */
156
+ export function repoIdentity(cwd) {
157
+ try {
158
+ const out = execFileSync('git', ['rev-parse', '--git-common-dir'], {
159
+ cwd,
160
+ encoding: 'utf8',
161
+ stdio: ['ignore', 'pipe', 'ignore'],
162
+ }).trim();
163
+ return join(cwd, out);
164
+ }
165
+ catch {
166
+ return null;
167
+ }
168
+ }
169
+ /**
170
+ * Find the current platform session with the strict single-candidate rule:
171
+ * exactly one live stash entry whose repo identity matches → that session;
172
+ * zero or multiple → null (caller degrades to id_source: agent).
173
+ */
174
+ export function resolveCurrentSession(projectRoot, now = new Date()) {
175
+ pruneStash(projectRoot, now);
176
+ const dir = stashDir(projectRoot);
177
+ if (!existsSync(dir))
178
+ return null;
179
+ const here = repoIdentity(projectRoot);
180
+ const candidates = [];
181
+ for (const f of readdirSync(dir)) {
182
+ if (!f.endsWith('.json'))
183
+ continue;
184
+ try {
185
+ const entry = JSON.parse(readFileSync(join(dir, f), 'utf8'));
186
+ const theirs = repoIdentity(entry.cwd);
187
+ if (here !== null && theirs !== null && here === theirs) {
188
+ candidates.push(entry);
189
+ }
190
+ else if (here === null && entry.cwd === projectRoot) {
191
+ candidates.push(entry);
192
+ }
193
+ }
194
+ catch {
195
+ // Unreadable stash entries are ignored here; pruneStash removes them.
196
+ }
197
+ }
198
+ return candidates.length === 1 ? candidates[0] : null;
199
+ }
200
+ //# sourceMappingURL=sessions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../src/cost/sessions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Post-hoc reconciliation: `aidlc cost sync` (FR4).
3
+ *
4
+ * Correlates platform usage records with instances via sessions.ndjson.
5
+ * Platform-id sessions match records by id equality; agent-id sessions
6
+ * match by interval overlap with a strict single-candidate rule. Appends
7
+ * `reconciled` entries only where coverage is not already held at equal or
8
+ * higher fidelity. Idempotent by construction; never guesses — ambiguity
9
+ * goes to the report, unattributable usage to unattributed.ndjson.
10
+ *
11
+ * Design: design.md §4.4
12
+ */
13
+ import { type ProviderEnv } from './providers/provider.js';
14
+ export interface SyncReport {
15
+ attributed: number;
16
+ skipped: string[];
17
+ unattributed: number;
18
+ }
19
+ /**
20
+ * Reconcile one or all instances. Streams platform records session by
21
+ * session; reports everything it skipped and why (FR4.3).
22
+ */
23
+ export declare function syncCosts(projectRoot: string, instanceFilter: string | null, claimTimeoutMinutes: number, env?: ProviderEnv): Promise<SyncReport>;
24
+ //# sourceMappingURL=sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/cost/sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAKxE,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACtB;AAkBD;;;GAGG;AACH,wBAAsB,SAAS,CAC7B,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,GAAG,IAAI,EAC7B,mBAAmB,EAAE,MAAM,EAC3B,GAAG,GAAE,WAA6B,GACjC,OAAO,CAAC,UAAU,CAAC,CA0GrB"}