@tracecart/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 +21 -0
- package/README.md +131 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +149 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/delta.d.ts +1 -0
- package/dist/commands/delta.js +19 -0
- package/dist/commands/delta.js.map +1 -0
- package/dist/commands/extract-prompt.d.ts +2 -0
- package/dist/commands/extract-prompt.js +35 -0
- package/dist/commands/extract-prompt.js.map +1 -0
- package/dist/commands/extract-validate.d.ts +2 -0
- package/dist/commands/extract-validate.js +21 -0
- package/dist/commands/extract-validate.js.map +1 -0
- package/dist/commands/finalize.d.ts +1 -0
- package/dist/commands/finalize.js +64 -0
- package/dist/commands/finalize.js.map +1 -0
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.js +33 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/match-prompt.d.ts +2 -0
- package/dist/commands/match-prompt.js +51 -0
- package/dist/commands/match-prompt.js.map +1 -0
- package/dist/commands/match-validate.d.ts +2 -0
- package/dist/commands/match-validate.js +15 -0
- package/dist/commands/match-validate.js.map +1 -0
- package/dist/commands/presets.d.ts +1 -0
- package/dist/commands/presets.js +14 -0
- package/dist/commands/presets.js.map +1 -0
- package/dist/commands/remainder.d.ts +1 -0
- package/dist/commands/remainder.js +19 -0
- package/dist/commands/remainder.js.map +1 -0
- package/dist/commands/reverse-extract-validate.d.ts +1 -0
- package/dist/commands/reverse-extract-validate.js +20 -0
- package/dist/commands/reverse-extract-validate.js.map +1 -0
- package/dist/commands/reverse-match-prompt.d.ts +2 -0
- package/dist/commands/reverse-match-prompt.js +50 -0
- package/dist/commands/reverse-match-prompt.js.map +1 -0
- package/dist/commands/reverse-match-validate.d.ts +1 -0
- package/dist/commands/reverse-match-validate.js +14 -0
- package/dist/commands/reverse-match-validate.js.map +1 -0
- package/dist/commands/split.d.ts +1 -0
- package/dist/commands/split.js +26 -0
- package/dist/commands/split.js.map +1 -0
- package/dist/commands/status.d.ts +1 -0
- package/dist/commands/status.js +34 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/update.d.ts +1 -0
- package/dist/commands/update.js +5 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/extract/extract.d.ts +37 -0
- package/dist/extract/extract.js +158 -0
- package/dist/extract/extract.js.map +1 -0
- package/dist/extract/remainder.d.ts +16 -0
- package/dist/extract/remainder.js +34 -0
- package/dist/extract/remainder.js.map +1 -0
- package/dist/match/coverage.d.ts +64 -0
- package/dist/match/coverage.js +375 -0
- package/dist/match/coverage.js.map +1 -0
- package/dist/output/delta.d.ts +46 -0
- package/dist/output/delta.js +155 -0
- package/dist/output/delta.js.map +1 -0
- package/dist/output/trace-map.d.ts +89 -0
- package/dist/output/trace-map.js +135 -0
- package/dist/output/trace-map.js.map +1 -0
- package/dist/parse/clause-split.d.ts +20 -0
- package/dist/parse/clause-split.js +185 -0
- package/dist/parse/clause-split.js.map +1 -0
- package/dist/parse/discover-inputs.d.ts +16 -0
- package/dist/parse/discover-inputs.js +97 -0
- package/dist/parse/discover-inputs.js.map +1 -0
- package/dist/parse/parse-document.d.ts +28 -0
- package/dist/parse/parse-document.js +141 -0
- package/dist/parse/parse-document.js.map +1 -0
- package/dist/preset.d.ts +18 -0
- package/dist/preset.js +85 -0
- package/dist/preset.js.map +1 -0
- package/package.json +58 -0
- package/presets/spec-coverage.json +15 -0
- package/prompts/coverage_check.txt +38 -0
- package/prompts/extract.txt +40 -0
- package/prompts/reverse_check.txt +36 -0
- package/templates/claude/commands/tracecart.md +217 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Gabor Tatar
|
|
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
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# tracecart
|
|
2
|
+
|
|
3
|
+
[](https://npmjs.com/package/@tracecart/cli)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
|
|
6
|
+
[Documentation](docs/) · [npm](https://www.npmjs.com/package/@tracecart/cli)
|
|
7
|
+
|
|
8
|
+
**Claim traceability tool** — extract atomic traces from source documents, verify coverage against targets, detect unsupported claims via reverse tracing.
|
|
9
|
+
|
|
10
|
+
**The problem:** You have input documents (client specs, meeting notes, emails) and generated implementation specs. How do you know the specs cover everything? Manual review misses implicit requirements, compound sentences, and cross-document overrides.
|
|
11
|
+
|
|
12
|
+
**tracecart** extracts atomic requirements, verifies each against your target documents, and optionally reverse-traces to catch hallucinations. Output: `trace-map.json` for editor visualization.
|
|
13
|
+
|
|
14
|
+
## How it works
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
SOURCE DOCUMENTS (specs, meetings, emails)
|
|
18
|
+
│
|
|
19
|
+
├─ Split into clauses (deterministic)
|
|
20
|
+
├─ Extract traces (LLM, max 3 iterations)
|
|
21
|
+
├─ Match traces against target (LLM)
|
|
22
|
+
├─ [--reverse] Reverse trace: target → source (LLM)
|
|
23
|
+
│
|
|
24
|
+
▼
|
|
25
|
+
trace-map.json → LSP → Editor annotations (Zed, VS Code)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Two layers:
|
|
29
|
+
- **Control layer** (deterministic TypeScript): clause splitting, validation, remainder tracking, finalization
|
|
30
|
+
- **Semantic layer** (LLM via Claude Code subagents): extraction, coverage matching, reverse tracing
|
|
31
|
+
|
|
32
|
+
## Install
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm install -g @tracecart/cli
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Quick start
|
|
39
|
+
|
|
40
|
+
### As a Claude Code skill
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# Install commands into your project
|
|
44
|
+
tracecart init
|
|
45
|
+
|
|
46
|
+
# Run forward pipeline
|
|
47
|
+
/tracecart source.md target.md
|
|
48
|
+
|
|
49
|
+
# Forward + reverse (detect unsupported claims in target)
|
|
50
|
+
/tracecart source.md target.md --reverse
|
|
51
|
+
|
|
52
|
+
# Custom preset
|
|
53
|
+
/tracecart source.md target.md --preset contract-compliance
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### CLI commands
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
tracecart split source.md # Split into clauses
|
|
60
|
+
tracecart extract-prompt clauses.json --source source.md --preset spec-coverage
|
|
61
|
+
tracecart extract-validate output.txt clauses.json --source source.md --preset spec-coverage
|
|
62
|
+
tracecart remainder clauses.json traces.json # Check uncovered clauses
|
|
63
|
+
tracecart match-prompt traces.json target.md --preset spec-coverage
|
|
64
|
+
tracecart match-validate output.txt traces.json --preset spec-coverage
|
|
65
|
+
tracecart finalize traces.json matches.json --source source.md --target target.md -o trace-map.json
|
|
66
|
+
tracecart presets # List available presets
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Presets
|
|
70
|
+
|
|
71
|
+
Presets define domain vocabulary (trace types, coverage statuses) and prompt templates. Switch presets for different comparison types without code changes.
|
|
72
|
+
|
|
73
|
+
| Preset | Description |
|
|
74
|
+
|--------|-------------|
|
|
75
|
+
| `spec-coverage` (default) | Source requirements → target spec coverage |
|
|
76
|
+
|
|
77
|
+
Custom presets: place `./presets/<name>.json` in your project.
|
|
78
|
+
|
|
79
|
+
See [docs/presets.md](docs/presets.md) for format and examples.
|
|
80
|
+
|
|
81
|
+
## Output
|
|
82
|
+
|
|
83
|
+
`trace-map.json` — consumed by the LSP server for inline editor annotations.
|
|
84
|
+
|
|
85
|
+
Coverage markers per trace:
|
|
86
|
+
- **COVERED** — target fully addresses the requirement
|
|
87
|
+
- **PARTIAL** — partially addressed, something missing
|
|
88
|
+
- **MISSING** — not addressed at all
|
|
89
|
+
- **DEFERRED** — explicitly out of scope
|
|
90
|
+
- **N/A** — meta-statement, doesn't need coverage
|
|
91
|
+
|
|
92
|
+
## Documentation
|
|
93
|
+
|
|
94
|
+
| Document | Description |
|
|
95
|
+
|----------|-------------|
|
|
96
|
+
| [Presets](docs/presets.md) | Preset format, customization, discovery |
|
|
97
|
+
| [Benchmarks](docs/benchmarks.md) | Extraction method comparison and scoring |
|
|
98
|
+
| [Testing](docs/testing.md) | Test fixtures, running tests, adding ground truth |
|
|
99
|
+
|
|
100
|
+
## Development
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
git clone https://github.com/tatargabor/tracecart.git
|
|
104
|
+
cd tracecart
|
|
105
|
+
npm install
|
|
106
|
+
npm run build
|
|
107
|
+
npm test
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
| Command | What it does |
|
|
111
|
+
|---------|-------------|
|
|
112
|
+
| `npm run build` | Compile TypeScript |
|
|
113
|
+
| `npm run dev` | Watch mode |
|
|
114
|
+
| `npm test` | Run tests (vitest) |
|
|
115
|
+
| `npm run lint` | Type-check without emit |
|
|
116
|
+
| `npm run clean` | Remove dist/ |
|
|
117
|
+
|
|
118
|
+
### Publishing
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
./scripts/publish.sh patch # bump → build → test → npm publish → git tag → GH release
|
|
122
|
+
./scripts/publish.sh minor
|
|
123
|
+
./scripts/publish.sh major
|
|
124
|
+
./scripts/publish.sh --dry-run patch # preview without changes
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Requires clean working tree, `gh` CLI, and npm auth.
|
|
128
|
+
|
|
129
|
+
## License
|
|
130
|
+
|
|
131
|
+
MIT
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { resolve, dirname } from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { loadPreset } from './preset.js';
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = dirname(__filename);
|
|
8
|
+
const PKG_ROOT = resolve(__dirname, '..');
|
|
9
|
+
const DEFAULT_PRESET = 'spec-coverage';
|
|
10
|
+
function loadJson(path) {
|
|
11
|
+
return JSON.parse(readFileSync(path, 'utf-8'));
|
|
12
|
+
}
|
|
13
|
+
function getVersion() {
|
|
14
|
+
const pkg = loadJson(resolve(PKG_ROOT, 'package.json'));
|
|
15
|
+
return pkg.version;
|
|
16
|
+
}
|
|
17
|
+
function printUsage() {
|
|
18
|
+
const cmds = [
|
|
19
|
+
'split', 'extract-prompt', 'extract-validate', 'remainder',
|
|
20
|
+
'match-prompt', 'match-validate',
|
|
21
|
+
'reverse-extract-validate', 'reverse-match-prompt', 'reverse-match-validate',
|
|
22
|
+
'finalize', 'status', 'delta',
|
|
23
|
+
'presets', 'init', 'update',
|
|
24
|
+
];
|
|
25
|
+
process.stderr.write(`tracecart v${getVersion()} — claim traceability tool\n\n`);
|
|
26
|
+
process.stderr.write(`Usage: tracecart <command> [--preset <name>] [args...]\n\n`);
|
|
27
|
+
process.stderr.write(`Commands:\n`);
|
|
28
|
+
for (const c of cmds) {
|
|
29
|
+
process.stderr.write(` ${c}\n`);
|
|
30
|
+
}
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
function extractPresetArg(args) {
|
|
34
|
+
const remaining = [];
|
|
35
|
+
let presetName = DEFAULT_PRESET;
|
|
36
|
+
for (let i = 0; i < args.length; i++) {
|
|
37
|
+
if (args[i] === '--preset' && args[i + 1]) {
|
|
38
|
+
presetName = args[++i];
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
remaining.push(args[i]);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return { presetName, remaining };
|
|
45
|
+
}
|
|
46
|
+
async function main() {
|
|
47
|
+
const args = process.argv.slice(2);
|
|
48
|
+
if (args.length === 0 || args[0] === '--help' || args[0] === '-h') {
|
|
49
|
+
printUsage();
|
|
50
|
+
}
|
|
51
|
+
if (args[0] === '--version' || args[0] === '-V') {
|
|
52
|
+
process.stdout.write(getVersion() + '\n');
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const cmd = args[0];
|
|
56
|
+
const cmdArgs = args.slice(1);
|
|
57
|
+
const { presetName, remaining } = extractPresetArg(cmdArgs);
|
|
58
|
+
let preset;
|
|
59
|
+
function getPreset() {
|
|
60
|
+
if (!preset)
|
|
61
|
+
preset = loadPreset(presetName, PKG_ROOT);
|
|
62
|
+
return preset;
|
|
63
|
+
}
|
|
64
|
+
switch (cmd) {
|
|
65
|
+
case 'split': {
|
|
66
|
+
const { cmdSplit } = await import('./commands/split.js');
|
|
67
|
+
await cmdSplit(remaining);
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
case 'extract-prompt': {
|
|
71
|
+
const { cmdExtractPrompt } = await import('./commands/extract-prompt.js');
|
|
72
|
+
await cmdExtractPrompt(remaining, PKG_ROOT, getPreset());
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
case 'extract-validate': {
|
|
76
|
+
const { cmdExtractValidate } = await import('./commands/extract-validate.js');
|
|
77
|
+
await cmdExtractValidate(remaining, getPreset());
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
case 'remainder': {
|
|
81
|
+
const { cmdRemainder } = await import('./commands/remainder.js');
|
|
82
|
+
await cmdRemainder(remaining);
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
case 'match-prompt': {
|
|
86
|
+
const { cmdMatchPrompt } = await import('./commands/match-prompt.js');
|
|
87
|
+
await cmdMatchPrompt(remaining, PKG_ROOT, getPreset());
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
case 'match-validate': {
|
|
91
|
+
const { cmdMatchValidate } = await import('./commands/match-validate.js');
|
|
92
|
+
await cmdMatchValidate(remaining, getPreset());
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
case 'reverse-extract-validate': {
|
|
96
|
+
const { cmdReverseExtractValidate } = await import('./commands/reverse-extract-validate.js');
|
|
97
|
+
await cmdReverseExtractValidate(remaining);
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
case 'reverse-match-prompt': {
|
|
101
|
+
const { cmdReverseMatchPrompt } = await import('./commands/reverse-match-prompt.js');
|
|
102
|
+
await cmdReverseMatchPrompt(remaining, PKG_ROOT, getPreset());
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
case 'reverse-match-validate': {
|
|
106
|
+
const { cmdReverseMatchValidate } = await import('./commands/reverse-match-validate.js');
|
|
107
|
+
await cmdReverseMatchValidate(remaining);
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
case 'finalize': {
|
|
111
|
+
const { cmdFinalize } = await import('./commands/finalize.js');
|
|
112
|
+
await cmdFinalize(remaining);
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
case 'status': {
|
|
116
|
+
const { cmdStatus } = await import('./commands/status.js');
|
|
117
|
+
await cmdStatus(remaining);
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
case 'delta': {
|
|
121
|
+
const { cmdDelta } = await import('./commands/delta.js');
|
|
122
|
+
await cmdDelta(remaining);
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
case 'presets': {
|
|
126
|
+
const { cmdPresets } = await import('./commands/presets.js');
|
|
127
|
+
await cmdPresets(PKG_ROOT);
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
case 'init': {
|
|
131
|
+
const { cmdInit } = await import('./commands/init.js');
|
|
132
|
+
await cmdInit(remaining, PKG_ROOT);
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
case 'update': {
|
|
136
|
+
const { cmdUpdate } = await import('./commands/update.js');
|
|
137
|
+
await cmdUpdate(remaining, PKG_ROOT);
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
default:
|
|
141
|
+
process.stderr.write(`Unknown command: ${cmd}\n`);
|
|
142
|
+
printUsage();
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
main().catch((err) => {
|
|
146
|
+
process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
147
|
+
process.exit(1);
|
|
148
|
+
});
|
|
149
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function cmdDelta(args: string[]): Promise<void>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { compare, formatText } from '../output/delta.js';
|
|
3
|
+
export async function cmdDelta(args) {
|
|
4
|
+
if (args.length < 2) {
|
|
5
|
+
process.stderr.write('Usage: tracecart delta <old.json> <new.json> [--json]\n');
|
|
6
|
+
process.exit(1);
|
|
7
|
+
}
|
|
8
|
+
const oldMap = JSON.parse(readFileSync(args[0], 'utf-8'));
|
|
9
|
+
const newMap = JSON.parse(readFileSync(args[1], 'utf-8'));
|
|
10
|
+
const useJson = args.includes('--json');
|
|
11
|
+
const delta = compare(oldMap, newMap);
|
|
12
|
+
if (useJson) {
|
|
13
|
+
process.stdout.write(JSON.stringify(delta, null, 2));
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
process.stdout.write(formatText(delta) + '\n');
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=delta.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delta.js","sourceRoot":"","sources":["../../src/commands/delta.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEzD,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAc;IAC3C,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,yDAAyD,CAAC,CAAC;QAChF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;IAC1D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;IAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAExC,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEtC,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACvD,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;IACjD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
function parseArgs(args) {
|
|
4
|
+
let sourceFile = '';
|
|
5
|
+
const clausesPath = args[0];
|
|
6
|
+
for (let i = 1; i < args.length; i++) {
|
|
7
|
+
if (args[i] === '--source' && args[i + 1]) {
|
|
8
|
+
sourceFile = args[++i];
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
return { clausesPath, sourceFile };
|
|
12
|
+
}
|
|
13
|
+
export async function cmdExtractPrompt(args, pkgRoot, preset) {
|
|
14
|
+
if (!args[0]) {
|
|
15
|
+
process.stderr.write('Usage: tracecart extract-prompt <clauses.json> [--source <file>] [--preset <name>]\n');
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
const { clausesPath, sourceFile } = parseArgs(args);
|
|
19
|
+
const data = JSON.parse(readFileSync(clausesPath, 'utf-8'));
|
|
20
|
+
const clauses = data.clauses ?? (Array.isArray(data) ? data : []);
|
|
21
|
+
const templateFile = preset.prompts.extract ?? 'extract.txt';
|
|
22
|
+
const templatePath = resolve(pkgRoot, 'prompts', templateFile);
|
|
23
|
+
const template = readFileSync(templatePath, 'utf-8');
|
|
24
|
+
const clauseLines = [];
|
|
25
|
+
for (const c of clauses) {
|
|
26
|
+
if (c.is_header || c.is_meta)
|
|
27
|
+
continue;
|
|
28
|
+
clauseLines.push(`[${c.clause_id}] ${c.text}`);
|
|
29
|
+
}
|
|
30
|
+
let prompt = template.replace('{clauses}', clauseLines.join('\n'));
|
|
31
|
+
prompt = prompt.replace('{trace_types}', preset.trace_types.join(' | '));
|
|
32
|
+
prompt = prompt.replace('{coverage_statuses}', preset.coverage_statuses.join(' | '));
|
|
33
|
+
process.stdout.write(prompt);
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=extract-prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract-prompt.js","sourceRoot":"","sources":["../../src/commands/extract-prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,SAAS,SAAS,CAAC,IAAc;IAC/B,IAAI,UAAU,GAAG,EAAE,CAAC;IACpB,MAAM,WAAW,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAE5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,UAAU,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YAAC,UAAU,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAAC,CAAC;IACxE,CAAC;IAED,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC;AACrC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAc,EAAE,OAAe,EAAE,MAAc;IACpF,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,sFAAsF,CAAC,CAAC;QAC7G,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IACpD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC;IAC5D,MAAM,OAAO,GAAa,IAAI,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAE5E,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,IAAI,aAAa,CAAC;IAC7D,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;IAC/D,MAAM,QAAQ,GAAG,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IAErD,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,OAAO;YAAE,SAAS;QACvC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACjD,CAAC;IAED,IAAI,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACnE,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,eAAe,EAAE,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IACzE,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAErF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { validateTraces } from '../extract/extract.js';
|
|
3
|
+
export async function cmdExtractValidate(args, preset) {
|
|
4
|
+
if (args.length < 2) {
|
|
5
|
+
process.stderr.write('Usage: tracecart extract-validate <llm_output.txt> <clauses.json> [--source <file>] [--preset <name>]\n');
|
|
6
|
+
process.exit(1);
|
|
7
|
+
}
|
|
8
|
+
const rawOutput = readFileSync(args[0], 'utf-8');
|
|
9
|
+
const data = JSON.parse(readFileSync(args[1], 'utf-8'));
|
|
10
|
+
const clauses = data.clauses ?? (Array.isArray(data) ? data : []);
|
|
11
|
+
let sourceFile = '';
|
|
12
|
+
for (let i = 2; i < args.length; i++) {
|
|
13
|
+
if (args[i] === '--source' && args[i + 1]) {
|
|
14
|
+
sourceFile = args[++i];
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
const validTypes = new Set(preset.trace_types.map(t => t.toUpperCase()));
|
|
18
|
+
const result = validateTraces(rawOutput, clauses, sourceFile, 'T', validTypes);
|
|
19
|
+
process.stdout.write(JSON.stringify(result, null, 2));
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=extract-validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract-validate.js","sourceRoot":"","sources":["../../src/commands/extract-validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAIvD,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,IAAc,EAAE,MAAc;IACrE,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,yGAAyG,CAAC,CAAC;QAChI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACjD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;IACxD,MAAM,OAAO,GAAa,IAAI,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAE5E,IAAI,UAAU,GAAG,EAAE,CAAC;IACpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,UAAU,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YAAC,UAAU,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAAC,CAAC;IACxE,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IACzE,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;IAC/E,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AACxD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function cmdFinalize(args: string[]): Promise<void>;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { applyMatches, resolveRefs } from '../match/coverage.js';
|
|
3
|
+
import { buildTraceMap } from '../output/trace-map.js';
|
|
4
|
+
export async function cmdFinalize(args) {
|
|
5
|
+
if (args.length < 2) {
|
|
6
|
+
process.stderr.write('Usage: tracecart finalize <traces.json> <matches.json> --source <file> --target <file> [--output trace-map.json]\n');
|
|
7
|
+
process.exit(1);
|
|
8
|
+
}
|
|
9
|
+
const tracesData = JSON.parse(readFileSync(args[0], 'utf-8'));
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
11
|
+
const traces = tracesData.traces ?? (Array.isArray(tracesData) ? tracesData : []);
|
|
12
|
+
const matchesData = JSON.parse(readFileSync(args[1], 'utf-8'));
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
14
|
+
const matches = matchesData.matches ?? (Array.isArray(matchesData) ? matchesData : []);
|
|
15
|
+
const sourceFiles = [];
|
|
16
|
+
const targetFiles = [];
|
|
17
|
+
let outputPath = null;
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
19
|
+
let untraced = [];
|
|
20
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
21
|
+
let reverseTraces = null;
|
|
22
|
+
let i = 2;
|
|
23
|
+
while (i < args.length) {
|
|
24
|
+
if (args[i] === '--source' && args[i + 1]) {
|
|
25
|
+
sourceFiles.push(args[++i]);
|
|
26
|
+
}
|
|
27
|
+
else if (args[i] === '--target' && args[i + 1]) {
|
|
28
|
+
targetFiles.push(args[++i]);
|
|
29
|
+
}
|
|
30
|
+
else if (args[i] === '--output' && args[i + 1]) {
|
|
31
|
+
outputPath = args[++i];
|
|
32
|
+
}
|
|
33
|
+
else if (args[i] === '--untraced' && args[i + 1]) {
|
|
34
|
+
const ud = JSON.parse(readFileSync(args[++i], 'utf-8'));
|
|
35
|
+
untraced = ud.remainder ?? (Array.isArray(ud) ? ud : []);
|
|
36
|
+
}
|
|
37
|
+
else if (args[i] === '--reverse-traces' && args[i + 1]) {
|
|
38
|
+
const rd = JSON.parse(readFileSync(args[++i], 'utf-8'));
|
|
39
|
+
reverseTraces = rd.traces ?? (Array.isArray(rd) ? rd : []);
|
|
40
|
+
}
|
|
41
|
+
i++;
|
|
42
|
+
}
|
|
43
|
+
const matchedTraces = applyMatches(traces, matches);
|
|
44
|
+
const resolvedTraces = resolveRefs(matchedTraces, targetFiles);
|
|
45
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
46
|
+
const traceMap = buildTraceMap(resolvedTraces, sourceFiles, targetFiles, untraced, undefined, (reverseTraces ?? undefined));
|
|
47
|
+
const outputJson = JSON.stringify(traceMap, null, 2);
|
|
48
|
+
if (outputPath) {
|
|
49
|
+
writeFileSync(outputPath, outputJson, 'utf-8');
|
|
50
|
+
process.stderr.write(`Written to ${outputPath}\n`);
|
|
51
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
52
|
+
const summary = traceMap.summary;
|
|
53
|
+
process.stderr.write(`Forward coverage: ${summary.coverage_score_pct}% ` +
|
|
54
|
+
`(${summary.covered}C/${summary.partial}P/${summary.missing}M/${summary.deferred}D)\n`);
|
|
55
|
+
if ('reverse_total' in summary) {
|
|
56
|
+
process.stderr.write(`Reverse coverage: ${summary.reverse_coverage_pct}% ` +
|
|
57
|
+
`(${summary.reverse_traced}T/${summary.reverse_partial_source ?? 0}P/${summary.reverse_untraced}U)\n`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
process.stdout.write(outputJson);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=finalize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"finalize.js","sourceRoot":"","sources":["../../src/commands/finalize.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function cmdInit(args: string[], pkgRoot: string): Promise<void>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
const TEMPLATE_REL = 'templates/claude/commands/tracecart.md';
|
|
4
|
+
const TARGET_REL = '.claude/commands/tracecart.md';
|
|
5
|
+
function extractVersion(content) {
|
|
6
|
+
const m = content.match(/<!--\s*tracecart\s+v([\d.]+)\s*-->/);
|
|
7
|
+
return m ? m[1] : null;
|
|
8
|
+
}
|
|
9
|
+
export async function cmdInit(args, pkgRoot) {
|
|
10
|
+
const projectDir = args[0] || process.cwd();
|
|
11
|
+
const templatePath = resolve(pkgRoot, TEMPLATE_REL);
|
|
12
|
+
const targetPath = resolve(projectDir, TARGET_REL);
|
|
13
|
+
if (!existsSync(templatePath)) {
|
|
14
|
+
process.stderr.write(`Error: template not found at ${templatePath}\n`);
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
const template = readFileSync(templatePath, 'utf-8');
|
|
18
|
+
const templateVersion = extractVersion(template);
|
|
19
|
+
if (existsSync(targetPath)) {
|
|
20
|
+
const existing = readFileSync(targetPath, 'utf-8');
|
|
21
|
+
const existingVersion = extractVersion(existing);
|
|
22
|
+
if (existingVersion === templateVersion) {
|
|
23
|
+
process.stderr.write(`Already up to date (v${templateVersion})\n`);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
process.stderr.write(`Updating ${TARGET_REL}: v${existingVersion ?? '?'} → v${templateVersion}\n`);
|
|
27
|
+
}
|
|
28
|
+
const targetDir = resolve(projectDir, '.claude/commands');
|
|
29
|
+
mkdirSync(targetDir, { recursive: true });
|
|
30
|
+
writeFileSync(targetPath, template, 'utf-8');
|
|
31
|
+
process.stderr.write(`Created ${TARGET_REL}\n`);
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,YAAY,GAAG,wCAAwC,CAAC;AAC9D,MAAM,UAAU,GAAG,+BAA+B,CAAC;AAEnD,SAAS,cAAc,CAAC,OAAe;IACrC,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;IAC9D,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACzB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAc,EAAE,OAAe;IAC3D,MAAM,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAC5C,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IACpD,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IAEnD,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC9B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gCAAgC,YAAY,IAAI,CAAC,CAAC;QACvE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,QAAQ,GAAG,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IACrD,MAAM,eAAe,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;IAEjD,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3B,MAAM,QAAQ,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QACnD,MAAM,eAAe,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;QAEjD,IAAI,eAAe,KAAK,eAAe,EAAE,CAAC;YACxC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,wBAAwB,eAAe,KAAK,CAAC,CAAC;YACnE,OAAO;QACT,CAAC;QAED,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,UAAU,MAAM,eAAe,IAAI,GAAG,OAAO,eAAe,IAAI,CAAC,CAAC;IACrG,CAAC;IAED,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;IAC1D,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1C,aAAa,CAAC,UAAU,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC7C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,UAAU,IAAI,CAAC,CAAC;AAClD,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import { batchTraces } from '../match/coverage.js';
|
|
4
|
+
export async function cmdMatchPrompt(args, pkgRoot, preset) {
|
|
5
|
+
if (args.length < 2) {
|
|
6
|
+
process.stderr.write('Usage: tracecart match-prompt <traces.json> <target.md> [--exclusions <text>] [--preset <name>]\n');
|
|
7
|
+
process.exit(1);
|
|
8
|
+
}
|
|
9
|
+
const tracesData = JSON.parse(readFileSync(args[0], 'utf-8'));
|
|
10
|
+
const traces = tracesData.traces ?? (Array.isArray(tracesData) ? tracesData : []);
|
|
11
|
+
const targetText = readFileSync(args[1], 'utf-8');
|
|
12
|
+
let exclusions = '';
|
|
13
|
+
for (let i = 2; i < args.length; i++) {
|
|
14
|
+
if (args[i] === '--exclusions' && args[i + 1]) {
|
|
15
|
+
exclusions = args[++i];
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
const templateFile = preset.prompts.coverage_check ?? 'coverage_check.txt';
|
|
19
|
+
const templatePath = resolve(pkgRoot, 'prompts', templateFile);
|
|
20
|
+
const template = readFileSync(templatePath, 'utf-8');
|
|
21
|
+
function formatPromptFromPreset(batch) {
|
|
22
|
+
const reqLines = [];
|
|
23
|
+
for (const t of batch) {
|
|
24
|
+
const tid = (t.id ?? t.sentence_id ?? '');
|
|
25
|
+
const text = (t.text ?? '');
|
|
26
|
+
const ttype = (t.type ?? 'REQUIREMENT');
|
|
27
|
+
const implicit = t.implicit ? ' [implicit]' : '';
|
|
28
|
+
reqLines.push(`[${tid}] (${ttype}${implicit}) ${text}`);
|
|
29
|
+
}
|
|
30
|
+
let prompt = template.replace('{requirements}', reqLines.join('\n'));
|
|
31
|
+
prompt = prompt.replace('{specs}', targetText);
|
|
32
|
+
prompt = prompt.replace('{exclusions}', exclusions || '(none specified)');
|
|
33
|
+
prompt = prompt.replace('{trace_types}', preset.trace_types.join(' | '));
|
|
34
|
+
prompt = prompt.replace('{coverage_statuses}', preset.coverage_statuses.join(' | '));
|
|
35
|
+
return prompt;
|
|
36
|
+
}
|
|
37
|
+
const batches = batchTraces(traces);
|
|
38
|
+
if (batches.length === 1) {
|
|
39
|
+
process.stdout.write(formatPromptFromPreset(traces));
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
for (let bi = 0; bi < batches.length; bi++) {
|
|
43
|
+
process.stderr.write(`--- BATCH ${bi + 1}/${batches.length} ---\n`);
|
|
44
|
+
process.stdout.write(formatPromptFromPreset(batches[bi]));
|
|
45
|
+
if (bi < batches.length - 1) {
|
|
46
|
+
process.stdout.write('\n---BATCH_SEPARATOR---\n');
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=match-prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"match-prompt.js","sourceRoot":"","sources":["../../src/commands/match-prompt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { validateMatches } from '../match/coverage.js';
|
|
3
|
+
export async function cmdMatchValidate(args, preset) {
|
|
4
|
+
if (args.length < 2) {
|
|
5
|
+
process.stderr.write('Usage: tracecart match-validate <llm_output.txt> <traces.json> [--preset <name>]\n');
|
|
6
|
+
process.exit(1);
|
|
7
|
+
}
|
|
8
|
+
const rawOutput = readFileSync(args[0], 'utf-8');
|
|
9
|
+
const tracesData = JSON.parse(readFileSync(args[1], 'utf-8'));
|
|
10
|
+
const traces = tracesData.traces ?? (Array.isArray(tracesData) ? tracesData : []);
|
|
11
|
+
const validStatuses = new Set(preset.coverage_statuses.map(s => s.toUpperCase()));
|
|
12
|
+
const result = validateMatches(rawOutput, traces, validStatuses);
|
|
13
|
+
process.stdout.write(JSON.stringify(result, null, 2));
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=match-validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"match-validate.js","sourceRoot":"","sources":["../../src/commands/match-validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAGvD,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAc,EAAE,MAAc;IACnE,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,oFAAoF,CAAC,CAAC;QAC3G,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACjD,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;IAC9D,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAElF,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IAClF,MAAM,MAAM,GAAG,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC;IACjE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AACxD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function cmdPresets(pkgRoot: string): Promise<void>;
|