@compaction/cli 0.1.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.
- package/LICENSE +663 -0
- package/README.md +319 -0
- package/dist/cli/commands/adapter.d.ts +2 -0
- package/dist/cli/commands/adapter.js +49 -0
- package/dist/cli/commands/aggregate.d.ts +2 -0
- package/dist/cli/commands/aggregate.js +60 -0
- package/dist/cli/commands/analyze.d.ts +2 -0
- package/dist/cli/commands/analyze.js +55 -0
- package/dist/cli/commands/apply-context.d.ts +12 -0
- package/dist/cli/commands/apply-context.js +80 -0
- package/dist/cli/commands/apply.d.ts +2 -0
- package/dist/cli/commands/apply.js +65 -0
- package/dist/cli/commands/approve.d.ts +2 -0
- package/dist/cli/commands/approve.js +55 -0
- package/dist/cli/commands/audit.d.ts +2 -0
- package/dist/cli/commands/audit.js +63 -0
- package/dist/cli/commands/billing-delta.d.ts +2 -0
- package/dist/cli/commands/billing-delta.js +246 -0
- package/dist/cli/commands/capture-claude-code.d.ts +19 -0
- package/dist/cli/commands/capture-claude-code.js +198 -0
- package/dist/cli/commands/capture-provider-usage.d.ts +35 -0
- package/dist/cli/commands/capture-provider-usage.js +113 -0
- package/dist/cli/commands/capture.d.ts +2 -0
- package/dist/cli/commands/capture.js +76 -0
- package/dist/cli/commands/compact.d.ts +2 -0
- package/dist/cli/commands/compact.js +206 -0
- package/dist/cli/commands/eval.d.ts +2 -0
- package/dist/cli/commands/eval.js +66 -0
- package/dist/cli/commands/export-session-seed.d.ts +11 -0
- package/dist/cli/commands/export-session-seed.js +42 -0
- package/dist/cli/commands/feedback.d.ts +2 -0
- package/dist/cli/commands/feedback.js +233 -0
- package/dist/cli/commands/import.d.ts +2 -0
- package/dist/cli/commands/import.js +60 -0
- package/dist/cli/commands/init.d.ts +2 -0
- package/dist/cli/commands/init.js +216 -0
- package/dist/cli/commands/integrations.d.ts +2 -0
- package/dist/cli/commands/integrations.js +29 -0
- package/dist/cli/commands/launch-treatment-session.d.ts +14 -0
- package/dist/cli/commands/launch-treatment-session.js +50 -0
- package/dist/cli/commands/optimize.d.ts +2 -0
- package/dist/cli/commands/optimize.js +33 -0
- package/dist/cli/commands/recommend.d.ts +4 -0
- package/dist/cli/commands/recommend.js +66 -0
- package/dist/cli/commands/review.d.ts +2 -0
- package/dist/cli/commands/review.js +60 -0
- package/dist/cli/commands/run.d.ts +2 -0
- package/dist/cli/commands/run.js +49 -0
- package/dist/cli/commands/spend.d.ts +2 -0
- package/dist/cli/commands/spend.js +24 -0
- package/dist/cli/commands/summary.d.ts +2 -0
- package/dist/cli/commands/summary.js +19 -0
- package/dist/cli/engine-degrade.d.ts +40 -0
- package/dist/cli/engine-degrade.js +59 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +59 -0
- package/dist/core/adapter-validation.d.ts +32 -0
- package/dist/core/adapter-validation.js +185 -0
- package/dist/core/adapters/claude-code-adapter.d.ts +51 -0
- package/dist/core/adapters/claude-code-adapter.js +539 -0
- package/dist/core/adapters/claude-code-discovery.d.ts +40 -0
- package/dist/core/adapters/claude-code-discovery.js +100 -0
- package/dist/core/aggregate-format.d.ts +62 -0
- package/dist/core/aggregate-format.js +349 -0
- package/dist/core/api-client/client.d.ts +43 -0
- package/dist/core/api-client/client.js +143 -0
- package/dist/core/api-client/config.d.ts +36 -0
- package/dist/core/api-client/config.js +44 -0
- package/dist/core/api-client/index.d.ts +13 -0
- package/dist/core/api-client/index.js +14 -0
- package/dist/core/api-client/payload.d.ts +93 -0
- package/dist/core/api-client/payload.js +180 -0
- package/dist/core/api-client/types.d.ts +95 -0
- package/dist/core/api-client/types.js +21 -0
- package/dist/core/artifact-writer.d.ts +2 -0
- package/dist/core/artifact-writer.js +14 -0
- package/dist/core/audit-report.d.ts +91 -0
- package/dist/core/audit-report.js +422 -0
- package/dist/core/billing-delta/billing-delta-record.d.ts +290 -0
- package/dist/core/billing-delta/billing-delta-record.js +394 -0
- package/dist/core/capture-adapter.d.ts +74 -0
- package/dist/core/capture-adapter.js +2 -0
- package/dist/core/command-runner.d.ts +29 -0
- package/dist/core/command-runner.js +96 -0
- package/dist/core/content-hash.d.ts +1 -0
- package/dist/core/content-hash.js +5 -0
- package/dist/core/cost-calculator.d.ts +6 -0
- package/dist/core/cost-calculator.js +20 -0
- package/dist/core/feedback-bundle.d.ts +159 -0
- package/dist/core/feedback-bundle.js +406 -0
- package/dist/core/openai-agents-capture.d.ts +66 -0
- package/dist/core/openai-agents-capture.js +475 -0
- package/dist/core/policy-types.d.ts +85 -0
- package/dist/core/policy-types.js +29 -0
- package/dist/core/pricing.d.ts +23 -0
- package/dist/core/pricing.js +55 -0
- package/dist/core/provider-usage/credential-redaction.d.ts +23 -0
- package/dist/core/provider-usage/credential-redaction.js +60 -0
- package/dist/core/provider-usage/provider-usage-adapter.d.ts +65 -0
- package/dist/core/provider-usage/provider-usage-adapter.js +147 -0
- package/dist/core/provider-usage/provider-usage-client.d.ts +89 -0
- package/dist/core/provider-usage/provider-usage-client.js +96 -0
- package/dist/core/report-generator.d.ts +7 -0
- package/dist/core/report-generator.js +275 -0
- package/dist/core/run-aggregator.d.ts +50 -0
- package/dist/core/run-aggregator.js +251 -0
- package/dist/core/run-labels.d.ts +52 -0
- package/dist/core/run-labels.js +80 -0
- package/dist/core/run-trace-converter.d.ts +3 -0
- package/dist/core/run-trace-converter.js +94 -0
- package/dist/core/safety-report.d.ts +52 -0
- package/dist/core/safety-report.js +440 -0
- package/dist/core/savings.d.ts +22 -0
- package/dist/core/savings.js +36 -0
- package/dist/core/session-aggregate.d.ts +211 -0
- package/dist/core/session-aggregate.js +490 -0
- package/dist/core/skill-injection-detector.d.ts +51 -0
- package/dist/core/skill-injection-detector.js +146 -0
- package/dist/core/spend-attribution.d.ts +169 -0
- package/dist/core/spend-attribution.js +611 -0
- package/dist/core/standalone-capsule-provenance.d.ts +4 -0
- package/dist/core/standalone-capsule-provenance.js +62 -0
- package/dist/core/state-capsule.d.ts +3 -0
- package/dist/core/state-capsule.js +147 -0
- package/dist/core/token-accounting.d.ts +62 -0
- package/dist/core/token-accounting.js +81 -0
- package/dist/core/token-estimator.d.ts +3 -0
- package/dist/core/token-estimator.js +18 -0
- package/dist/core/trace-adapters.d.ts +53 -0
- package/dist/core/trace-adapters.js +714 -0
- package/dist/core/trace-fingerprint.d.ts +79 -0
- package/dist/core/trace-fingerprint.js +102 -0
- package/dist/core/trace-intake.d.ts +41 -0
- package/dist/core/trace-intake.js +164 -0
- package/dist/core/trace-parser.d.ts +203 -0
- package/dist/core/trace-parser.js +143 -0
- package/dist/core/types.d.ts +238 -0
- package/dist/core/types.js +2 -0
- package/dist/core/usage-metadata.d.ts +51 -0
- package/dist/core/usage-metadata.js +122 -0
- package/dist/core/waste-detector.d.ts +8 -0
- package/dist/core/waste-detector.js +58 -0
- package/package.json +90 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { assertTraceAdapterSource, getTraceAdapter, parseTraceAdapterRawContent } from "./trace-adapters.js";
|
|
5
|
+
const adapterValidationRoot = path.join(".compaction", "adapter-validations");
|
|
6
|
+
const validationHarnessLimitations = [
|
|
7
|
+
"Adapter Fixture Harness v0 is local and file-based only.",
|
|
8
|
+
"It validates exported or synthetic fixture files through the existing adapter contract and registry.",
|
|
9
|
+
"It does not mutate the source fixture file.",
|
|
10
|
+
"It does not upload data or call model/provider APIs.",
|
|
11
|
+
"It is not a live Claude Code, Codex, Cursor, OpenAI, Anthropic, LangChain, GitHub, or provider/runtime integration.",
|
|
12
|
+
"Codex exec JSONL support validates local export files only; live provider/runtime integrations remain future work."
|
|
13
|
+
];
|
|
14
|
+
function markdownList(values, emptyText) {
|
|
15
|
+
if (values.length === 0) {
|
|
16
|
+
return `- ${emptyText}`;
|
|
17
|
+
}
|
|
18
|
+
return values.map((value) => `- ${value}`).join("\n");
|
|
19
|
+
}
|
|
20
|
+
function buildValidationId(inputPath, source, generatedAt, rawContent) {
|
|
21
|
+
const digest = createHash("sha256").update(`${inputPath}\n${source}\n${generatedAt}\n${rawContent}`).digest("hex").slice(0, 10);
|
|
22
|
+
const timestamp = generatedAt.replace(/[-:.]/g, "").replace("T", "-").replace("Z", "");
|
|
23
|
+
return `adapter-validation-${timestamp}-${digest}`;
|
|
24
|
+
}
|
|
25
|
+
function formatAdapterValidationMarkdown(report) {
|
|
26
|
+
return [
|
|
27
|
+
"# Adapter Validation Report",
|
|
28
|
+
"",
|
|
29
|
+
"## Summary",
|
|
30
|
+
"",
|
|
31
|
+
`- Validation ID: ${report.validation_id}`,
|
|
32
|
+
`- Status: ${report.status}`,
|
|
33
|
+
`- Supported format detected: ${report.supported_format_detected ? "yes" : "no"}`,
|
|
34
|
+
`- Output trace ID: ${report.output_trace_id ?? "none"}`,
|
|
35
|
+
`- Message count: ${report.message_count}`,
|
|
36
|
+
`- Generated at: ${report.generated_at}`,
|
|
37
|
+
"",
|
|
38
|
+
"## Source",
|
|
39
|
+
"",
|
|
40
|
+
`- Input path: ${report.input_path}`,
|
|
41
|
+
`- Requested source: ${report.source}`,
|
|
42
|
+
"",
|
|
43
|
+
"## Adapter",
|
|
44
|
+
"",
|
|
45
|
+
`- Adapter ID: ${report.adapter_id}`,
|
|
46
|
+
"- Adapter selected from the local trace adapter registry.",
|
|
47
|
+
"- Live provider/runtime integration: no",
|
|
48
|
+
"",
|
|
49
|
+
"## Normalization",
|
|
50
|
+
"",
|
|
51
|
+
markdownList(report.normalization_steps, "No normalization steps were applied."),
|
|
52
|
+
"",
|
|
53
|
+
"## Warnings",
|
|
54
|
+
"",
|
|
55
|
+
markdownList(report.warnings, "No warnings."),
|
|
56
|
+
"",
|
|
57
|
+
"## Failures",
|
|
58
|
+
"",
|
|
59
|
+
markdownList(report.failures, "No failures."),
|
|
60
|
+
"",
|
|
61
|
+
"## Recommended Next Command",
|
|
62
|
+
"",
|
|
63
|
+
report.recommended_next_command ? `\`${report.recommended_next_command}\`` : "No next command is recommended until validation succeeds.",
|
|
64
|
+
"",
|
|
65
|
+
"## Limitations",
|
|
66
|
+
"",
|
|
67
|
+
markdownList(report.limitations, "No limitations recorded."),
|
|
68
|
+
""
|
|
69
|
+
].join("\n");
|
|
70
|
+
}
|
|
71
|
+
function buildReport(params) {
|
|
72
|
+
return {
|
|
73
|
+
validation_id: params.validationId,
|
|
74
|
+
generated_at: params.generatedAt,
|
|
75
|
+
input_path: params.inputPath,
|
|
76
|
+
source: params.source,
|
|
77
|
+
adapter_id: params.adapterId,
|
|
78
|
+
status: params.status,
|
|
79
|
+
output_trace_id: params.outputTraceId,
|
|
80
|
+
message_count: params.messageCount,
|
|
81
|
+
supported_format_detected: params.supportedFormatDetected,
|
|
82
|
+
warnings: params.warnings,
|
|
83
|
+
failures: params.failures,
|
|
84
|
+
normalization_steps: params.normalizationSteps,
|
|
85
|
+
skipped_fields: params.skippedFields,
|
|
86
|
+
limitations: params.limitations,
|
|
87
|
+
recommended_next_command: params.status === "fail" ? null : `compaction analyze ${params.normalizedTracePath}`
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
async function writeAdapterValidationArtifacts(outputDirectory, report, normalizedTrace) {
|
|
91
|
+
await mkdir(outputDirectory, { recursive: true });
|
|
92
|
+
const normalizedTracePath = path.join(outputDirectory, "normalized-trace.json");
|
|
93
|
+
const validationReportJsonPath = path.join(outputDirectory, "adapter-validation.json");
|
|
94
|
+
const validationReportMarkdownPath = path.join(outputDirectory, "adapter-validation.md");
|
|
95
|
+
if (normalizedTrace) {
|
|
96
|
+
await writeFile(normalizedTracePath, `${JSON.stringify(normalizedTrace, null, 2)}\n`, "utf8");
|
|
97
|
+
}
|
|
98
|
+
await writeFile(validationReportJsonPath, `${JSON.stringify(report, null, 2)}\n`, "utf8");
|
|
99
|
+
await writeFile(validationReportMarkdownPath, formatAdapterValidationMarkdown(report), "utf8");
|
|
100
|
+
return {
|
|
101
|
+
report,
|
|
102
|
+
normalizedTrace,
|
|
103
|
+
paths: {
|
|
104
|
+
outputDirectory,
|
|
105
|
+
normalizedTracePath,
|
|
106
|
+
validationReportJsonPath,
|
|
107
|
+
validationReportMarkdownPath
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
export async function validateAdapterFixtureFile(inputPath, source, outputRoot = adapterValidationRoot) {
|
|
112
|
+
assertTraceAdapterSource(source);
|
|
113
|
+
const rawContent = await readFile(inputPath, "utf8");
|
|
114
|
+
const generatedAt = new Date().toISOString();
|
|
115
|
+
const validationId = buildValidationId(inputPath, source, generatedAt, rawContent);
|
|
116
|
+
const outputDirectory = path.join(outputRoot, validationId);
|
|
117
|
+
const normalizedTracePath = path.join(outputDirectory, "normalized-trace.json");
|
|
118
|
+
const adapter = getTraceAdapter(source);
|
|
119
|
+
const limitations = [...validationHarnessLimitations, ...adapter.limitations];
|
|
120
|
+
const parsedInput = parseTraceAdapterRawContent(rawContent, source);
|
|
121
|
+
if (parsedInput.failures.length > 0 || parsedInput.input === null) {
|
|
122
|
+
const report = buildReport({
|
|
123
|
+
validationId,
|
|
124
|
+
generatedAt,
|
|
125
|
+
inputPath,
|
|
126
|
+
source,
|
|
127
|
+
adapterId: adapter.id,
|
|
128
|
+
status: "fail",
|
|
129
|
+
outputTraceId: null,
|
|
130
|
+
messageCount: 0,
|
|
131
|
+
supportedFormatDetected: false,
|
|
132
|
+
warnings: [],
|
|
133
|
+
failures: parsedInput.failures,
|
|
134
|
+
normalizationSteps: [...parsedInput.normalization_steps, "Skipped adapter canHandle and normalize because the fixture could not be parsed."],
|
|
135
|
+
skippedFields: [],
|
|
136
|
+
limitations,
|
|
137
|
+
normalizedTracePath
|
|
138
|
+
});
|
|
139
|
+
return writeAdapterValidationArtifacts(outputDirectory, report, null);
|
|
140
|
+
}
|
|
141
|
+
const normalizationSteps = [...parsedInput.normalization_steps, `Selected adapter ${adapter.id} from the local adapter registry.`];
|
|
142
|
+
const canHandle = adapter.canHandle(parsedInput.input);
|
|
143
|
+
normalizationSteps.push(`Ran adapter canHandle for source ${source}: ${canHandle ? "supported" : "unsupported"}.`);
|
|
144
|
+
if (!canHandle) {
|
|
145
|
+
const report = buildReport({
|
|
146
|
+
validationId,
|
|
147
|
+
generatedAt,
|
|
148
|
+
inputPath,
|
|
149
|
+
source,
|
|
150
|
+
adapterId: adapter.id,
|
|
151
|
+
status: "fail",
|
|
152
|
+
outputTraceId: null,
|
|
153
|
+
messageCount: 0,
|
|
154
|
+
supportedFormatDetected: false,
|
|
155
|
+
warnings: [],
|
|
156
|
+
failures: [`Adapter ${adapter.id} cannot handle this fixture shape for source ${source}.`],
|
|
157
|
+
normalizationSteps: [...normalizationSteps, "Skipped normalize because canHandle returned false."],
|
|
158
|
+
skippedFields: [],
|
|
159
|
+
limitations,
|
|
160
|
+
normalizedTracePath
|
|
161
|
+
});
|
|
162
|
+
return writeAdapterValidationArtifacts(outputDirectory, report, null);
|
|
163
|
+
}
|
|
164
|
+
const result = adapter.normalize(parsedInput.input, { rawContent });
|
|
165
|
+
const normalizedTrace = result.status === "fail" ? null : result.trace;
|
|
166
|
+
const report = buildReport({
|
|
167
|
+
validationId,
|
|
168
|
+
generatedAt,
|
|
169
|
+
inputPath,
|
|
170
|
+
source,
|
|
171
|
+
adapterId: adapter.id,
|
|
172
|
+
status: result.status,
|
|
173
|
+
outputTraceId: normalizedTrace?.id ?? null,
|
|
174
|
+
messageCount: normalizedTrace?.messages.length ?? 0,
|
|
175
|
+
supportedFormatDetected: result.trace !== null,
|
|
176
|
+
warnings: result.warnings,
|
|
177
|
+
failures: result.failures,
|
|
178
|
+
normalizationSteps: [...normalizationSteps, "Ran adapter normalize for the local fixture.", ...result.normalization_steps],
|
|
179
|
+
skippedFields: result.skipped_fields,
|
|
180
|
+
limitations,
|
|
181
|
+
normalizedTracePath
|
|
182
|
+
});
|
|
183
|
+
return writeAdapterValidationArtifacts(outputDirectory, report, normalizedTrace);
|
|
184
|
+
}
|
|
185
|
+
//# sourceMappingURL=adapter-validation.js.map
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { CaptureAdapter, CaptureAdapterInput, CapturedRun } from "../capture-adapter.js";
|
|
2
|
+
export declare const PRIVACY_WARNING: string;
|
|
3
|
+
/**
|
|
4
|
+
* Lightweight metadata for a single discoverable Claude Code session.
|
|
5
|
+
*
|
|
6
|
+
* Computed by reusing the existing adapter parser (`readJsonlEntries` +
|
|
7
|
+
* `processEntries` + `discoverSubagentJSONLFiles`) so the counts match what
|
|
8
|
+
* `normalize()` would produce — NOT a re-implemented parser. This is metadata
|
|
9
|
+
* ONLY: no session message content is surfaced.
|
|
10
|
+
*/
|
|
11
|
+
export interface ClaudeCodeSessionMetadata {
|
|
12
|
+
/** Absolute path to the session JSONL file (ready for `--session <path>`). */
|
|
13
|
+
sessionPath: string;
|
|
14
|
+
/** Project slug (the `<slug>` directory name under projects root). */
|
|
15
|
+
projectSlug: string;
|
|
16
|
+
/** Decoded project working directory, if recoverable from the slug / entries. */
|
|
17
|
+
projectDir: string | undefined;
|
|
18
|
+
/** Session ID parsed from the session entries, or null if unknown. */
|
|
19
|
+
sessionId: string | null;
|
|
20
|
+
/** Earliest entry timestamp (ISO 8601), or undefined if none present. */
|
|
21
|
+
firstTimestamp: string | undefined;
|
|
22
|
+
/** Latest entry timestamp (ISO 8601), or undefined if none present. */
|
|
23
|
+
lastTimestamp: string | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* Message count as the adapter would produce for the MAIN session
|
|
26
|
+
* (subagent messages are only merged when --include-subagents is passed,
|
|
27
|
+
* so they are NOT counted here, matching the default capture).
|
|
28
|
+
*/
|
|
29
|
+
messageCount: number;
|
|
30
|
+
/** Number of subagent JSONL files discoverable under <session-id>/subagents/. */
|
|
31
|
+
subagentCount: number;
|
|
32
|
+
/**
|
|
33
|
+
* True when at least one assistant entry carries a provider `usage` object —
|
|
34
|
+
* i.e. the capture would set provider_reported_tokens: true.
|
|
35
|
+
*/
|
|
36
|
+
providerReportedUsagePresent: boolean;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Scan a single Claude Code session JSONL file for discovery metadata.
|
|
40
|
+
*
|
|
41
|
+
* Reuses the existing parser exactly (no re-implementation): it reads the same
|
|
42
|
+
* entries `normalize()` reads, runs the same `processEntries` over the main
|
|
43
|
+
* session, and counts subagent files via the same `discoverSubagentJSONLFiles`.
|
|
44
|
+
* Reads only the given session file (and lists its subagents directory).
|
|
45
|
+
* Surfaces metadata only; never returns message content.
|
|
46
|
+
*/
|
|
47
|
+
export declare function scanSessionMetadata(sessionPath: string, projectSlug: string): Promise<ClaudeCodeSessionMetadata>;
|
|
48
|
+
export declare class ClaudeCodeAdapter implements CaptureAdapter {
|
|
49
|
+
readonly id = "claude-code";
|
|
50
|
+
normalize(input: CaptureAdapterInput): Promise<CapturedRun>;
|
|
51
|
+
}
|