llm-mock-server 1.0.6 → 1.0.7
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/dist/cli/cli.d.ts +3 -0
- package/dist/cli/cli.d.ts.map +1 -0
- package/dist/cli/cli.js +103 -0
- package/dist/cli/cli.js.map +1 -0
- package/dist/cli/validators.d.ts +7 -0
- package/dist/cli/validators.d.ts.map +1 -0
- package/dist/cli/validators.js +53 -0
- package/dist/cli/validators.js.map +1 -0
- package/dist/formats/anthropic/index.d.ts +1 -1
- package/dist/formats/anthropic/index.d.ts.map +1 -1
- package/dist/formats/anthropic/index.js +1 -1
- package/dist/formats/anthropic/index.js.map +1 -1
- package/dist/formats/anthropic/parse.d.ts +2 -2
- package/dist/formats/anthropic/parse.d.ts.map +1 -1
- package/dist/formats/anthropic/parse.js +4 -2
- package/dist/formats/anthropic/parse.js.map +1 -1
- package/dist/formats/anthropic/schema.d.ts +1 -1
- package/dist/formats/anthropic/schema.d.ts.map +1 -1
- package/dist/formats/anthropic/schema.js +9 -4
- package/dist/formats/anthropic/schema.js.map +1 -1
- package/dist/formats/anthropic/serialize.d.ts +2 -2
- package/dist/formats/anthropic/serialize.d.ts.map +1 -1
- package/dist/formats/anthropic/serialize.js +76 -19
- package/dist/formats/anthropic/serialize.js.map +1 -1
- package/dist/formats/openai/chat-completions/index.d.ts +3 -0
- package/dist/formats/openai/chat-completions/index.d.ts.map +1 -0
- package/dist/formats/openai/chat-completions/index.js +13 -0
- package/dist/formats/openai/chat-completions/index.js.map +1 -0
- package/dist/formats/openai/chat-completions/parse.d.ts +4 -0
- package/dist/formats/openai/chat-completions/parse.d.ts.map +1 -0
- package/dist/formats/openai/chat-completions/parse.js +33 -0
- package/dist/formats/openai/chat-completions/parse.js.map +1 -0
- package/dist/formats/openai/chat-completions/schema.d.ts +93 -0
- package/dist/formats/openai/chat-completions/schema.d.ts.map +1 -0
- package/dist/formats/openai/chat-completions/schema.js +74 -0
- package/dist/formats/openai/chat-completions/schema.js.map +1 -0
- package/dist/formats/openai/chat-completions/serialize.d.ts +10 -0
- package/dist/formats/openai/chat-completions/serialize.d.ts.map +1 -0
- package/dist/formats/openai/chat-completions/serialize.js +99 -0
- package/dist/formats/openai/chat-completions/serialize.js.map +1 -0
- package/dist/formats/openai/responses/index.d.ts +3 -0
- package/dist/formats/openai/responses/index.d.ts.map +1 -0
- package/dist/formats/openai/responses/index.js +13 -0
- package/dist/formats/openai/responses/index.js.map +1 -0
- package/dist/formats/openai/responses/parse.d.ts +4 -0
- package/dist/formats/openai/responses/parse.d.ts.map +1 -0
- package/dist/formats/openai/responses/parse.js +51 -0
- package/dist/formats/openai/responses/parse.js.map +1 -0
- package/dist/formats/openai/responses/schema.d.ts +103 -0
- package/dist/formats/openai/responses/schema.d.ts.map +1 -0
- package/dist/formats/openai/responses/schema.js +71 -0
- package/dist/formats/openai/responses/schema.js.map +1 -0
- package/dist/formats/openai/responses/serialize.d.ts +10 -0
- package/dist/formats/openai/responses/serialize.d.ts.map +1 -0
- package/dist/formats/openai/responses/serialize.js +273 -0
- package/dist/formats/openai/responses/serialize.js.map +1 -0
- package/dist/formats/request-helpers.d.ts +1 -1
- package/dist/formats/request-helpers.d.ts.map +1 -1
- package/dist/formats/request-helpers.js.map +1 -1
- package/dist/formats/serialize-helpers.d.ts +1 -1
- package/dist/formats/serialize-helpers.d.ts.map +1 -1
- package/dist/formats/serialize-helpers.js +6 -3
- package/dist/formats/serialize-helpers.js.map +1 -1
- package/dist/formats/types.d.ts +2 -1
- package/dist/formats/types.d.ts.map +1 -1
- package/dist/history.d.ts +6 -2
- package/dist/history.d.ts.map +1 -1
- package/dist/history.js +2 -0
- package/dist/history.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/loader.d.ts +1 -1
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +26 -9
- package/dist/loader.js.map +1 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +12 -4
- package/dist/logger.js.map +1 -1
- package/dist/mock-server.d.ts +44 -48
- package/dist/mock-server.d.ts.map +1 -1
- package/dist/mock-server.js +37 -85
- package/dist/mock-server.js.map +1 -1
- package/dist/route-handler.d.ts +1 -1
- package/dist/route-handler.d.ts.map +1 -1
- package/dist/route-handler.js +19 -7
- package/dist/route-handler.js.map +1 -1
- package/dist/rule-builder.d.ts +21 -0
- package/dist/rule-builder.d.ts.map +1 -0
- package/dist/rule-builder.js +58 -0
- package/dist/rule-builder.js.map +1 -0
- package/dist/rule-engine.d.ts +3 -1
- package/dist/rule-engine.d.ts.map +1 -1
- package/dist/rule-engine.js +7 -2
- package/dist/rule-engine.js.map +1 -1
- package/dist/sse-writer.d.ts +1 -1
- package/dist/sse-writer.d.ts.map +1 -1
- package/dist/types/reply.d.ts +51 -8
- package/dist/types/reply.d.ts.map +1 -1
- package/dist/types/request.d.ts +21 -6
- package/dist/types/request.d.ts.map +1 -1
- package/dist/types/rule.d.ts +65 -7
- package/dist/types/rule.d.ts.map +1 -1
- package/dist/types.d.ts +3 -3
- package/dist/types.d.ts.map +1 -1
- package/package.json +15 -9
- package/.claude/skills/desloppify/SKILL.md +0 -308
- package/.desloppify/external_review_sessions/ext_20260315_000339_a6cdc3e6/canonical_import_20260315_000801.json +0 -242
- package/.desloppify/external_review_sessions/ext_20260315_000339_a6cdc3e6/canonical_import_20260315_000905.json +0 -248
- package/.desloppify/external_review_sessions/ext_20260315_000339_a6cdc3e6/canonical_import_20260315_000917.json +0 -248
- package/.desloppify/external_review_sessions/ext_20260315_000339_a6cdc3e6/canonical_import_20260315_000950.json +0 -311
- package/.desloppify/external_review_sessions/ext_20260315_000339_a6cdc3e6/claude_launch_prompt.md +0 -17
- package/.desloppify/external_review_sessions/ext_20260315_000339_a6cdc3e6/review_result.json +0 -255
- package/.desloppify/external_review_sessions/ext_20260315_000339_a6cdc3e6/review_result.template.json +0 -22
- package/.desloppify/external_review_sessions/ext_20260315_000339_a6cdc3e6/reviewer_instructions.md +0 -20
- package/.desloppify/external_review_sessions/ext_20260315_000339_a6cdc3e6/session.json +0 -20
- package/.desloppify/external_review_sessions/ext_20260315_045546_0587ea3b/canonical_import_20260315_050000.json +0 -286
- package/.desloppify/external_review_sessions/ext_20260315_045546_0587ea3b/canonical_import_20260315_050028.json +0 -303
- package/.desloppify/external_review_sessions/ext_20260315_045546_0587ea3b/claude_launch_prompt.md +0 -17
- package/.desloppify/external_review_sessions/ext_20260315_045546_0587ea3b/review_result.json +0 -297
- package/.desloppify/external_review_sessions/ext_20260315_045546_0587ea3b/review_result.template.json +0 -22
- package/.desloppify/external_review_sessions/ext_20260315_045546_0587ea3b/reviewer_instructions.md +0 -20
- package/.desloppify/external_review_sessions/ext_20260315_045546_0587ea3b/session.json +0 -20
- package/.desloppify/query.json +0 -1312
- package/.desloppify/review_packet_blind.json +0 -1249
- package/.desloppify/review_packets/holistic_packet_20260315_000339.json +0 -1471
- package/.desloppify/review_packets/holistic_packet_20260315_045546.json +0 -1480
- package/.desloppify/review_packets/holistic_packet_20260315_185401.json +0 -1407
- package/.desloppify/review_packets/holistic_packet_20260315_185613.json +0 -1407
- package/.desloppify/state-typescript.json +0 -8438
- package/.desloppify/state-typescript.json.bak +0 -8432
- package/.desloppify/subagents/runs/20260315_185401/logs/batch-1.log +0 -384
- package/.desloppify/subagents/runs/20260315_185401/logs/batch-10.log +0 -484
- package/.desloppify/subagents/runs/20260315_185401/logs/batch-2.log +0 -408
- package/.desloppify/subagents/runs/20260315_185401/logs/batch-3.log +0 -416
- package/.desloppify/subagents/runs/20260315_185401/logs/batch-4.log +0 -360
- package/.desloppify/subagents/runs/20260315_185401/logs/batch-5.log +0 -360
- package/.desloppify/subagents/runs/20260315_185401/logs/batch-6.log +0 -364
- package/.desloppify/subagents/runs/20260315_185401/logs/batch-7.log +0 -428
- package/.desloppify/subagents/runs/20260315_185401/logs/batch-8.log +0 -388
- package/.desloppify/subagents/runs/20260315_185401/logs/batch-9.log +0 -500
- package/.desloppify/subagents/runs/20260315_185401/prompts/batch-1.md +0 -83
- package/.desloppify/subagents/runs/20260315_185401/prompts/batch-10.md +0 -108
- package/.desloppify/subagents/runs/20260315_185401/prompts/batch-2.md +0 -89
- package/.desloppify/subagents/runs/20260315_185401/prompts/batch-3.md +0 -91
- package/.desloppify/subagents/runs/20260315_185401/prompts/batch-4.md +0 -77
- package/.desloppify/subagents/runs/20260315_185401/prompts/batch-5.md +0 -77
- package/.desloppify/subagents/runs/20260315_185401/prompts/batch-6.md +0 -78
- package/.desloppify/subagents/runs/20260315_185401/prompts/batch-7.md +0 -94
- package/.desloppify/subagents/runs/20260315_185401/prompts/batch-8.md +0 -84
- package/.desloppify/subagents/runs/20260315_185401/prompts/batch-9.md +0 -112
- package/.desloppify/subagents/runs/20260315_185401/results/batch-1.raw.txt +0 -0
- package/.desloppify/subagents/runs/20260315_185401/results/batch-10.raw.txt +0 -0
- package/.desloppify/subagents/runs/20260315_185401/results/batch-2.raw.txt +0 -0
- package/.desloppify/subagents/runs/20260315_185401/results/batch-3.raw.txt +0 -0
- package/.desloppify/subagents/runs/20260315_185401/results/batch-4.raw.txt +0 -0
- package/.desloppify/subagents/runs/20260315_185401/results/batch-5.raw.txt +0 -0
- package/.desloppify/subagents/runs/20260315_185401/results/batch-6.raw.txt +0 -0
- package/.desloppify/subagents/runs/20260315_185401/results/batch-7.raw.txt +0 -0
- package/.desloppify/subagents/runs/20260315_185401/results/batch-8.raw.txt +0 -0
- package/.desloppify/subagents/runs/20260315_185401/results/batch-9.raw.txt +0 -0
- package/.desloppify/subagents/runs/20260315_185401/run.log +0 -36
- package/.desloppify/subagents/runs/20260315_185401/run_summary.json +0 -156
- package/.desloppify/subagents/runs/20260315_185613/holistic_findings_merged.json +0 -741
- package/.desloppify/subagents/runs/20260315_185613/logs/batch-1.log +0 -579
- package/.desloppify/subagents/runs/20260315_185613/logs/batch-10.log +0 -1537
- package/.desloppify/subagents/runs/20260315_185613/logs/batch-2.log +0 -829
- package/.desloppify/subagents/runs/20260315_185613/logs/batch-3.log +0 -927
- package/.desloppify/subagents/runs/20260315_185613/logs/batch-4.log +0 -429
- package/.desloppify/subagents/runs/20260315_185613/logs/batch-5.log +0 -276
- package/.desloppify/subagents/runs/20260315_185613/logs/batch-6.log +0 -450
- package/.desloppify/subagents/runs/20260315_185613/logs/batch-7.log +0 -730
- package/.desloppify/subagents/runs/20260315_185613/logs/batch-8.log +0 -698
- package/.desloppify/subagents/runs/20260315_185613/logs/batch-9.log +0 -938
- package/.desloppify/subagents/runs/20260315_185613/prompts/batch-1.md +0 -83
- package/.desloppify/subagents/runs/20260315_185613/prompts/batch-10.md +0 -108
- package/.desloppify/subagents/runs/20260315_185613/prompts/batch-2.md +0 -89
- package/.desloppify/subagents/runs/20260315_185613/prompts/batch-3.md +0 -91
- package/.desloppify/subagents/runs/20260315_185613/prompts/batch-4.md +0 -77
- package/.desloppify/subagents/runs/20260315_185613/prompts/batch-5.md +0 -77
- package/.desloppify/subagents/runs/20260315_185613/prompts/batch-6.md +0 -78
- package/.desloppify/subagents/runs/20260315_185613/prompts/batch-7.md +0 -94
- package/.desloppify/subagents/runs/20260315_185613/prompts/batch-8.md +0 -84
- package/.desloppify/subagents/runs/20260315_185613/prompts/batch-9.md +0 -112
- package/.desloppify/subagents/runs/20260315_185613/results/batch-1.raw.txt +0 -78
- package/.desloppify/subagents/runs/20260315_185613/results/batch-10.raw.txt +0 -242
- package/.desloppify/subagents/runs/20260315_185613/results/batch-2.raw.txt +0 -102
- package/.desloppify/subagents/runs/20260315_185613/results/batch-3.raw.txt +0 -94
- package/.desloppify/subagents/runs/20260315_185613/results/batch-4.raw.txt +0 -86
- package/.desloppify/subagents/runs/20260315_185613/results/batch-5.raw.txt +0 -1
- package/.desloppify/subagents/runs/20260315_185613/results/batch-6.raw.txt +0 -87
- package/.desloppify/subagents/runs/20260315_185613/results/batch-7.raw.txt +0 -1
- package/.desloppify/subagents/runs/20260315_185613/results/batch-8.raw.txt +0 -107
- package/.desloppify/subagents/runs/20260315_185613/results/batch-9.raw.txt +0 -67
- package/.desloppify/subagents/runs/20260315_185613/run.log +0 -96
- package/.desloppify/subagents/runs/20260315_185613/run_summary.json +0 -156
- package/.editorconfig +0 -12
- package/.github/dependabot.yml +0 -11
- package/.github/workflows/docs.yml +0 -46
- package/.github/workflows/test.yml +0 -40
- package/.markdownlint.jsonc +0 -11
- package/.node-version +0 -1
- package/.oxfmtrc.json +0 -9
- package/.oxlintrc.json +0 -35
- package/docs/ARCHITECTURE.md +0 -125
- package/scorecard.png +0 -0
- package/src/cli/cli.ts +0 -141
- package/src/cli/validators.ts +0 -68
- package/src/formats/anthropic/index.ts +0 -14
- package/src/formats/anthropic/parse.ts +0 -70
- package/src/formats/anthropic/schema.ts +0 -74
- package/src/formats/anthropic/serialize.ts +0 -179
- package/src/formats/openai/chat-completions/index.ts +0 -14
- package/src/formats/openai/chat-completions/parse.ts +0 -47
- package/src/formats/openai/chat-completions/schema.ts +0 -92
- package/src/formats/openai/chat-completions/serialize.ts +0 -146
- package/src/formats/openai/responses/index.ts +0 -14
- package/src/formats/openai/responses/parse.ts +0 -73
- package/src/formats/openai/responses/schema.ts +0 -86
- package/src/formats/openai/responses/serialize.ts +0 -328
- package/src/formats/request-helpers.ts +0 -56
- package/src/formats/serialize-helpers.ts +0 -43
- package/src/formats/types.ts +0 -26
- package/src/history.ts +0 -70
- package/src/index.ts +0 -46
- package/src/loader.ts +0 -246
- package/src/logger.ts +0 -70
- package/src/mock-server.ts +0 -203
- package/src/route-handler.ts +0 -144
- package/src/rule-builder.ts +0 -73
- package/src/rule-engine.ts +0 -165
- package/src/sse-writer.ts +0 -35
- package/src/types/reply.ts +0 -92
- package/src/types/request.ts +0 -56
- package/src/types/rule.ts +0 -125
- package/src/types.ts +0 -24
- package/test/cli-validators.test.ts +0 -151
- package/test/formats/anthropic.test.ts +0 -336
- package/test/formats/openai.test.ts +0 -316
- package/test/formats/parse-helpers.test.ts +0 -315
- package/test/formats/responses.test.ts +0 -380
- package/test/helpers/make-req.ts +0 -18
- package/test/history.test.ts +0 -361
- package/test/loader.test.ts +0 -333
- package/test/logger.test.ts +0 -344
- package/test/mock-server.test.ts +0 -619
- package/test/rule-engine.test.ts +0 -229
- package/tsconfig.json +0 -24
- package/tsconfig.test.json +0 -11
- package/typedoc.json +0 -9
- package/vitest.config.ts +0 -18
|
@@ -1,927 +0,0 @@
|
|
|
1
|
-
ATTEMPT 1/3
|
|
2
|
-
$ codex exec --ephemeral -C /Users/suyash.x.srijan/Documents/Personal_Projects/llm-mock-server -s workspace-write -c approval_policy="never" -c model_reasoning_effort="low" -o /Users/suyash.x.srijan/Documents/Personal_Projects/llm-mock-server/.desloppify/subagents/runs/20260315_185613/results/batch-3.raw.txt You are a focused subagent reviewer for a single holistic investigation batch.
|
|
3
|
-
|
|
4
|
-
Repository root: /Users/suyash.x.srijan/Documents/Personal_Projects/llm-mock-server
|
|
5
|
-
Blind packet: /Users/suyash.x.srijan/Documents/Personal_Projects/llm-mock-server/.desloppify/review_packet_blind.json
|
|
6
|
-
Batch index: 3
|
|
7
|
-
Batch name: Abstractions & Dependencies
|
|
8
|
-
Batch dimensions: abstraction_fitness, mid_level_elegance, low_level_elegance
|
|
9
|
-
Batch rationale: abstraction hotspots (wrappers/interfaces/param bags), dep cycles
|
|
10
|
-
|
|
11
|
-
Files assigned:
|
|
12
|
-
- test/cli-validators.test.ts
|
|
13
|
-
- src/mock-server.ts
|
|
14
|
-
- test/formats/anthropic.test.ts
|
|
15
|
-
- src/cli.ts
|
|
16
|
-
- test/mock-server.test.ts
|
|
17
|
-
- src/formats/responses/serialize.ts
|
|
18
|
-
- test/formats/responses.test.ts
|
|
19
|
-
- test/history.test.ts
|
|
20
|
-
- src/rule-engine.ts
|
|
21
|
-
- src/history.ts
|
|
22
|
-
- src/loader.ts
|
|
23
|
-
- test/formats/openai.test.ts
|
|
24
|
-
- test/loader.test.ts
|
|
25
|
-
- test/logger.test.ts
|
|
26
|
-
- src/formats/openai/serialize.ts
|
|
27
|
-
|
|
28
|
-
Task requirements:
|
|
29
|
-
1. Read the blind packet and follow `system_prompt` constraints exactly.
|
|
30
|
-
1a. If previously flagged issues are listed above, use them as context for your review.
|
|
31
|
-
Verify whether each still applies to the current code. Do not re-report fixed or
|
|
32
|
-
wontfix issues. Use them as starting points to look deeper — inspect adjacent code
|
|
33
|
-
and related modules for defects the prior review may have missed.
|
|
34
|
-
1c. Think structurally: when you spot multiple individual issues that share a common
|
|
35
|
-
root cause (missing abstraction, duplicated pattern, inconsistent convention),
|
|
36
|
-
explain the deeper structural issue in the finding, not just the surface symptom.
|
|
37
|
-
If the pattern is significant enough, report the structural issue as its own finding
|
|
38
|
-
with appropriate fix_scope ('multi_file_refactor' or 'architectural_change') and
|
|
39
|
-
use `root_cause_cluster` to connect related symptom findings together.
|
|
40
|
-
2. Evaluate ONLY listed files and ONLY listed dimensions for this batch.
|
|
41
|
-
3. Return 0-10 high-quality findings for this batch (empty array allowed).
|
|
42
|
-
3a. Do not suppress real defects to keep scores high; report every material issue you can support with evidence.
|
|
43
|
-
3b. Do not default to 100. Reserve 100 for genuinely exemplary evidence in this batch.
|
|
44
|
-
4. Score/finding consistency is required: broader or more severe findings MUST lower dimension scores.
|
|
45
|
-
4a. Any dimension scored below 85.0 MUST include explicit feedback: add at least one finding with the same `dimension` and a non-empty actionable `suggestion`.
|
|
46
|
-
5. Every finding must include `related_files` with at least 2 files when possible.
|
|
47
|
-
6. Every finding must include `dimension`, `identifier`, `summary`, `evidence`, `suggestion`, and `confidence`.
|
|
48
|
-
7. Every finding must include `impact_scope` and `fix_scope`.
|
|
49
|
-
8. Every scored dimension MUST include dimension_notes with concrete evidence.
|
|
50
|
-
9. If a dimension score is >85.0, include `issues_preventing_higher_score` in dimension_notes.
|
|
51
|
-
10. Use exactly one decimal place for every assessment and abstraction sub-axis score.
|
|
52
|
-
11. Ignore prior chat context and any target-threshold assumptions.
|
|
53
|
-
12. Do not edit repository files.
|
|
54
|
-
13. Return ONLY valid JSON, no markdown fences.
|
|
55
|
-
|
|
56
|
-
Scope enums:
|
|
57
|
-
- impact_scope: "local" | "module" | "subsystem" | "codebase"
|
|
58
|
-
- fix_scope: "single_edit" | "multi_file_refactor" | "architectural_change"
|
|
59
|
-
|
|
60
|
-
Output schema:
|
|
61
|
-
{
|
|
62
|
-
"batch": "Abstractions & Dependencies",
|
|
63
|
-
"batch_index": 3,
|
|
64
|
-
"assessments": {"<dimension>": <0-100 with one decimal place>},
|
|
65
|
-
"dimension_notes": {
|
|
66
|
-
"<dimension>": {
|
|
67
|
-
"evidence": ["specific code observations"],
|
|
68
|
-
"impact_scope": "local|module|subsystem|codebase",
|
|
69
|
-
"fix_scope": "single_edit|multi_file_refactor|architectural_change",
|
|
70
|
-
"confidence": "high|medium|low",
|
|
71
|
-
"issues_preventing_higher_score": "required when score >85.0",
|
|
72
|
-
"sub_axes": {"abstraction_leverage": 0-100 with one decimal place, "indirection_cost": 0-100 with one decimal place, "interface_honesty": 0-100 with one decimal place} // required for abstraction_fitness when evidence supports it
|
|
73
|
-
}
|
|
74
|
-
},
|
|
75
|
-
"findings": [{
|
|
76
|
-
"dimension": "<dimension>",
|
|
77
|
-
"identifier": "short_id",
|
|
78
|
-
"summary": "one-line defect summary",
|
|
79
|
-
"related_files": ["relative/path.py"],
|
|
80
|
-
"evidence": ["specific code observation"],
|
|
81
|
-
"suggestion": "concrete fix recommendation",
|
|
82
|
-
"confidence": "high|medium|low",
|
|
83
|
-
"impact_scope": "local|module|subsystem|codebase",
|
|
84
|
-
"fix_scope": "single_edit|multi_file_refactor|architectural_change",
|
|
85
|
-
"root_cause_cluster": "optional_cluster_name_when_supported_by_history"
|
|
86
|
-
}],
|
|
87
|
-
"retrospective": {
|
|
88
|
-
"root_causes": ["optional: concise root-cause hypotheses"],
|
|
89
|
-
"likely_symptoms": ["optional: identifiers that look symptom-level"],
|
|
90
|
-
"possible_false_positives": ["optional: prior concept keys likely mis-scoped"]
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
STDOUT:
|
|
96
|
-
{
|
|
97
|
-
"batch": "Abstractions & Dependencies",
|
|
98
|
-
"batch_index": 3,
|
|
99
|
-
"assessments": {
|
|
100
|
-
"abstraction_fitness": 82.0,
|
|
101
|
-
"mid_level_elegance": 84.0,
|
|
102
|
-
"low_level_elegance": 88.0
|
|
103
|
-
},
|
|
104
|
-
"dimension_notes": {
|
|
105
|
-
"abstraction_fitness": {
|
|
106
|
-
"evidence": [
|
|
107
|
-
"src/mock-server.ts builds sequence rules inline in when().replySequence(), including mapping entries and calling createSequenceResolver, then sets rule.remaining.",
|
|
108
|
-
"src/loader.ts repeats near-identical sequence rule wiring in addSequenceRule(), including entry mapping, createSequenceResolver, and rule.remaining."
|
|
109
|
-
],
|
|
110
|
-
"impact_scope": "module",
|
|
111
|
-
"fix_scope": "multi_file_refactor",
|
|
112
|
-
"confidence": "high",
|
|
113
|
-
"issues_preventing_higher_score": "Sequence-rule construction is duplicated in two modules, making future option/behavior changes easy to miss in one path.",
|
|
114
|
-
"sub_axes": {
|
|
115
|
-
"abstraction_leverage": 79.0,
|
|
116
|
-
"indirection_cost": 84.0,
|
|
117
|
-
"interface_honesty": 83.0
|
|
118
|
-
}
|
|
119
|
-
},
|
|
120
|
-
"mid_level_elegance": {
|
|
121
|
-
"evidence": [
|
|
122
|
-
"src/mock-server.ts registers routes from the formats array (openaiFormat/anthropicFormat/responsesFormat) and relies on each format’s route.",
|
|
123
|
-
"src/cli.ts prints a hard-coded endpoints string instead of deriving from the same formats registry."
|
|
124
|
-
],
|
|
125
|
-
"impact_scope": "module",
|
|
126
|
-
"fix_scope": "multi_file_refactor",
|
|
127
|
-
"confidence": "medium",
|
|
128
|
-
"issues_preventing_higher_score": "Endpoint listing is a manual seam between CLI output and runtime route registration, which can drift when adding/removing formats."
|
|
129
|
-
},
|
|
130
|
-
"low_level_elegance": {
|
|
131
|
-
"evidence": [
|
|
132
|
-
"src/formats/responses/serialize.ts serialize() mixes header creation, block construction, chunk flattening, and response finalization in one dense function.",
|
|
133
|
-
"src/formats/openai/serialize.ts serialize() builds text/tool chunks, finish/usage chunks, and envelopes inline without local extraction."
|
|
134
|
-
],
|
|
135
|
-
"impact_scope": "local",
|
|
136
|
-
"fix_scope": "single_edit",
|
|
137
|
-
"confidence": "medium",
|
|
138
|
-
"issues_preventing_higher_score": "Serialization functions are readable but locally dense; small extractions would make the control flow more intention-revealing."
|
|
139
|
-
}
|
|
140
|
-
},
|
|
141
|
-
"findings": [
|
|
142
|
-
{
|
|
143
|
-
"dimension": "abstraction_fitness",
|
|
144
|
-
"identifier": "sequence_rule_duplication",
|
|
145
|
-
"summary": "Sequence rule construction is duplicated across MockServer and loader, risking drift.",
|
|
146
|
-
"related_files": [
|
|
147
|
-
"src/mock-server.ts",
|
|
148
|
-
"src/loader.ts",
|
|
149
|
-
"src/rule-engine.ts"
|
|
150
|
-
],
|
|
151
|
-
"evidence": [
|
|
152
|
-
"src/mock-server.ts when().replySequence() maps entries, calls createSequenceResolver, mutates rule.resolve and rule.remaining.",
|
|
153
|
-
"src/loader.ts addSequenceRule() performs the same mapping/resolve/remaining steps with a slightly different entry shape."
|
|
154
|
-
],
|
|
155
|
-
"suggestion": "Extract a shared helper (e.g., in src/rule-engine.ts) that accepts normalized sequence steps and applies createSequenceResolver + remaining, then reuse it from both MockServer and loader.",
|
|
156
|
-
"confidence": "high",
|
|
157
|
-
"impact_scope": "module",
|
|
158
|
-
"fix_scope": "multi_file_refactor",
|
|
159
|
-
"root_cause_cluster": "sequence_rule_duplication"
|
|
160
|
-
},
|
|
161
|
-
{
|
|
162
|
-
"dimension": "mid_level_elegance",
|
|
163
|
-
"identifier": "format_registry_split",
|
|
164
|
-
"summary": "CLI hard-codes endpoints while MockServer derives routes from format modules.",
|
|
165
|
-
"related_files": [
|
|
166
|
-
"src/mock-server.ts",
|
|
167
|
-
"src/cli.ts"
|
|
168
|
-
],
|
|
169
|
-
"evidence": [
|
|
170
|
-
"src/mock-server.ts registers routes by iterating formats[] with per-format route values.",
|
|
171
|
-
"src/cli.ts prints a static endpoints list string that must be updated manually."
|
|
172
|
-
],
|
|
173
|
-
"suggestion": "Expose a single formats registry (or route list) and have the CLI render endpoints from it, avoiding cross-module drift.",
|
|
174
|
-
"confidence": "medium",
|
|
175
|
-
"impact_scope": "module",
|
|
176
|
-
"fix_scope": "multi_file_refactor"
|
|
177
|
-
}
|
|
178
|
-
],
|
|
179
|
-
"retrospective": {
|
|
180
|
-
"root_causes": [
|
|
181
|
-
"Shared logic exists without a single owning abstraction, leading to duplication across modules."
|
|
182
|
-
],
|
|
183
|
-
"likely_symptoms": [
|
|
184
|
-
"sequence_rule_duplication",
|
|
185
|
-
"format_registry_split"
|
|
186
|
-
],
|
|
187
|
-
"possible_false_positives": []
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
STDERR:
|
|
193
|
-
OpenAI Codex v0.114.0 (research preview)
|
|
194
|
-
--------
|
|
195
|
-
workdir: /Users/suyash.x.srijan/Documents/Personal_Projects/llm-mock-server
|
|
196
|
-
model: gpt-5.2-codex
|
|
197
|
-
provider: openai
|
|
198
|
-
approval: never
|
|
199
|
-
sandbox: workspace-write [workdir, /tmp, $TMPDIR, /Users/suyash.x.srijan/.codex/memories]
|
|
200
|
-
reasoning effort: low
|
|
201
|
-
reasoning summaries: none
|
|
202
|
-
session id: 019cf2dd-bc97-7be0-b843-65bc1c0098fd
|
|
203
|
-
--------
|
|
204
|
-
user
|
|
205
|
-
You are a focused subagent reviewer for a single holistic investigation batch.
|
|
206
|
-
|
|
207
|
-
Repository root: /Users/suyash.x.srijan/Documents/Personal_Projects/llm-mock-server
|
|
208
|
-
Blind packet: /Users/suyash.x.srijan/Documents/Personal_Projects/llm-mock-server/.desloppify/review_packet_blind.json
|
|
209
|
-
Batch index: 3
|
|
210
|
-
Batch name: Abstractions & Dependencies
|
|
211
|
-
Batch dimensions: abstraction_fitness, mid_level_elegance, low_level_elegance
|
|
212
|
-
Batch rationale: abstraction hotspots (wrappers/interfaces/param bags), dep cycles
|
|
213
|
-
|
|
214
|
-
Files assigned:
|
|
215
|
-
- test/cli-validators.test.ts
|
|
216
|
-
- src/mock-server.ts
|
|
217
|
-
- test/formats/anthropic.test.ts
|
|
218
|
-
- src/cli.ts
|
|
219
|
-
- test/mock-server.test.ts
|
|
220
|
-
- src/formats/responses/serialize.ts
|
|
221
|
-
- test/formats/responses.test.ts
|
|
222
|
-
- test/history.test.ts
|
|
223
|
-
- src/rule-engine.ts
|
|
224
|
-
- src/history.ts
|
|
225
|
-
- src/loader.ts
|
|
226
|
-
- test/formats/openai.test.ts
|
|
227
|
-
- test/loader.test.ts
|
|
228
|
-
- test/logger.test.ts
|
|
229
|
-
- src/formats/openai/serialize.ts
|
|
230
|
-
|
|
231
|
-
Task requirements:
|
|
232
|
-
1. Read the blind packet and follow `system_prompt` constraints exactly.
|
|
233
|
-
1a. If previously flagged issues are listed above, use them as context for your review.
|
|
234
|
-
Verify whether each still applies to the current code. Do not re-report fixed or
|
|
235
|
-
wontfix issues. Use them as starting points to look deeper — inspect adjacent code
|
|
236
|
-
and related modules for defects the prior review may have missed.
|
|
237
|
-
1c. Think structurally: when you spot multiple individual issues that share a common
|
|
238
|
-
root cause (missing abstraction, duplicated pattern, inconsistent convention),
|
|
239
|
-
explain the deeper structural issue in the finding, not just the surface symptom.
|
|
240
|
-
If the pattern is significant enough, report the structural issue as its own finding
|
|
241
|
-
with appropriate fix_scope ('multi_file_refactor' or 'architectural_change') and
|
|
242
|
-
use `root_cause_cluster` to connect related symptom findings together.
|
|
243
|
-
2. Evaluate ONLY listed files and ONLY listed dimensions for this batch.
|
|
244
|
-
3. Return 0-10 high-quality findings for this batch (empty array allowed).
|
|
245
|
-
3a. Do not suppress real defects to keep scores high; report every material issue you can support with evidence.
|
|
246
|
-
3b. Do not default to 100. Reserve 100 for genuinely exemplary evidence in this batch.
|
|
247
|
-
4. Score/finding consistency is required: broader or more severe findings MUST lower dimension scores.
|
|
248
|
-
4a. Any dimension scored below 85.0 MUST include explicit feedback: add at least one finding with the same `dimension` and a non-empty actionable `suggestion`.
|
|
249
|
-
5. Every finding must include `related_files` with at least 2 files when possible.
|
|
250
|
-
6. Every finding must include `dimension`, `identifier`, `summary`, `evidence`, `suggestion`, and `confidence`.
|
|
251
|
-
7. Every finding must include `impact_scope` and `fix_scope`.
|
|
252
|
-
8. Every scored dimension MUST include dimension_notes with concrete evidence.
|
|
253
|
-
9. If a dimension score is >85.0, include `issues_preventing_higher_score` in dimension_notes.
|
|
254
|
-
10. Use exactly one decimal place for every assessment and abstraction sub-axis score.
|
|
255
|
-
11. Ignore prior chat context and any target-threshold assumptions.
|
|
256
|
-
12. Do not edit repository files.
|
|
257
|
-
13. Return ONLY valid JSON, no markdown fences.
|
|
258
|
-
|
|
259
|
-
Scope enums:
|
|
260
|
-
- impact_scope: "local" | "module" | "subsystem" | "codebase"
|
|
261
|
-
- fix_scope: "single_edit" | "multi_file_refactor" | "architectural_change"
|
|
262
|
-
|
|
263
|
-
Output schema:
|
|
264
|
-
{
|
|
265
|
-
"batch": "Abstractions & Dependencies",
|
|
266
|
-
"batch_index": 3,
|
|
267
|
-
"assessments": {"<dimension>": <0-100 with one decimal place>},
|
|
268
|
-
"dimension_notes": {
|
|
269
|
-
"<dimension>": {
|
|
270
|
-
"evidence": ["specific code observations"],
|
|
271
|
-
"impact_scope": "local|module|subsystem|codebase",
|
|
272
|
-
"fix_scope": "single_edit|multi_file_refactor|architectural_change",
|
|
273
|
-
"confidence": "high|medium|low",
|
|
274
|
-
"issues_preventing_higher_score": "required when score >85.0",
|
|
275
|
-
"sub_axes": {"abstraction_leverage": 0-100 with one decimal place, "indirection_cost": 0-100 with one decimal place, "interface_honesty": 0-100 with one decimal place} // required for abstraction_fitness when evidence supports it
|
|
276
|
-
}
|
|
277
|
-
},
|
|
278
|
-
"findings": [{
|
|
279
|
-
"dimension": "<dimension>",
|
|
280
|
-
"identifier": "short_id",
|
|
281
|
-
"summary": "one-line defect summary",
|
|
282
|
-
"related_files": ["relative/path.py"],
|
|
283
|
-
"evidence": ["specific code observation"],
|
|
284
|
-
"suggestion": "concrete fix recommendation",
|
|
285
|
-
"confidence": "high|medium|low",
|
|
286
|
-
"impact_scope": "local|module|subsystem|codebase",
|
|
287
|
-
"fix_scope": "single_edit|multi_file_refactor|architectural_change",
|
|
288
|
-
"root_cause_cluster": "optional_cluster_name_when_supported_by_history"
|
|
289
|
-
}],
|
|
290
|
-
"retrospective": {
|
|
291
|
-
"root_causes": ["optional: concise root-cause hypotheses"],
|
|
292
|
-
"likely_symptoms": ["optional: identifiers that look symptom-level"],
|
|
293
|
-
"possible_false_positives": ["optional: prior concept keys likely mis-scoped"]
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
mcp startup: no servers
|
|
298
|
-
|
|
299
|
-
thinking
|
|
300
|
-
**Reading blind packet with cat**
|
|
301
|
-
exec
|
|
302
|
-
/bin/zsh -lc ls in /Users/suyash.x.srijan/Documents/Personal_Projects/llm-mock-server succeeded in 0ms:
|
|
303
|
-
LICENCE
|
|
304
|
-
README.md
|
|
305
|
-
coverage
|
|
306
|
-
dist
|
|
307
|
-
docs
|
|
308
|
-
node_modules
|
|
309
|
-
package-lock.json
|
|
310
|
-
package.json
|
|
311
|
-
scorecard.png
|
|
312
|
-
src
|
|
313
|
-
test
|
|
314
|
-
tsconfig.json
|
|
315
|
-
tsconfig.test.json
|
|
316
|
-
vitest.config.ts
|
|
317
|
-
exec
|
|
318
|
-
/bin/zsh -lc 'cat .desloppify/review_packet_blind.json' in /Users/suyash.x.srijan/Documents/Personal_Projects/llm-mock-server succeeded in 0ms:
|
|
319
|
-
{
|
|
320
|
-
"command": "review",
|
|
321
|
-
"mode": "holistic",
|
|
322
|
-
"language": "typescript",
|
|
323
|
-
"dimensions": [
|
|
324
|
-
"cross_module_architecture",
|
|
325
|
-
"convention_outlier",
|
|
326
|
-
"error_consistency",
|
|
327
|
-
"abstraction_fitness",
|
|
328
|
-
"api_surface_coherence",
|
|
329
|
-
"authorization_consistency",
|
|
330
|
-
"ai_generated_debt",
|
|
331
|
-
"incomplete_migration",
|
|
332
|
-
"package_organization",
|
|
333
|
-
"high_level_elegance",
|
|
334
|
-
"mid_level_elegance",
|
|
335
|
-
"low_level_elegance",
|
|
336
|
-
"design_coherence"
|
|
337
|
-
],
|
|
338
|
-
"dimension_prompts": {
|
|
339
|
-
|
|
340
|
-
thinking
|
|
341
|
-
**Preparing to read relevant files**
|
|
342
|
-
exec
|
|
343
|
-
/bin/zsh -lc "sed -n '1,200p' src/mock-server.ts" in /Users/suyash.x.srijan/Documents/Personal_Projects/llm-mock-server succeeded in 0ms:
|
|
344
|
-
import Fastify from "fastify";
|
|
345
|
-
import type { FastifyInstance } from "fastify";
|
|
346
|
-
import type {
|
|
347
|
-
Match,
|
|
348
|
-
PendingRule,
|
|
349
|
-
Reply,
|
|
350
|
-
ReplyOptions,
|
|
351
|
-
Resolver,
|
|
352
|
-
Rule,
|
|
353
|
-
RuleHandle,
|
|
354
|
-
RuleSummary,
|
|
355
|
-
SequenceEntry,
|
|
356
|
-
} from "./types.js";
|
|
357
|
-
import { RuleEngine, createSequenceResolver } from "./rule-engine.js";
|
|
358
|
-
import { RequestHistory } from "./history.js";
|
|
359
|
-
import { openaiFormat } from "./formats/openai/index.js";
|
|
360
|
-
import { anthropicFormat } from "./formats/anthropic/index.js";
|
|
361
|
-
import { responsesFormat } from "./formats/responses/index.js";
|
|
362
|
-
import type { Format } from "./formats/types.js";
|
|
363
|
-
import { Logger } from "./logger.js";
|
|
364
|
-
exec
|
|
365
|
-
/bin/zsh -lc "sed -n '1,200p' src/cli.ts" in /Users/suyash.x.srijan/Documents/Personal_Projects/llm-mock-server succeeded in 0ms:
|
|
366
|
-
#!/usr/bin/env node
|
|
367
|
-
|
|
368
|
-
import { watch } from "node:fs";
|
|
369
|
-
import { createRequire } from "node:module";
|
|
370
|
-
import { Command } from "commander";
|
|
371
|
-
import pc from "picocolors";
|
|
372
|
-
import { MockServer } from "./mock-server.js";
|
|
373
|
-
import { Logger } from "./logger.js";
|
|
374
|
-
import {
|
|
375
|
-
parsePort,
|
|
376
|
-
parseHost,
|
|
377
|
-
parseLogLevel,
|
|
378
|
-
parseChunkSize,
|
|
379
|
-
parseLatency,
|
|
380
|
-
} from "./cli-validators.js";
|
|
381
|
-
|
|
382
|
-
const require = createRequire(import.meta.url);
|
|
383
|
-
const { version } = require("../package.json") as { version: string };
|
|
384
|
-
|
|
385
|
-
const WATCH_DEBOUNCE_MS = 100;
|
|
386
|
-
exec
|
|
387
|
-
/bin/zsh -lc "sed -n '1,200p' src/formats/responses/serialize.ts" in /Users/suyash.x.srijan/Documents/Personal_Projects/llm-mock-server succeeded in 0ms:
|
|
388
|
-
import type { ReplyObject, ReplyOptions, ToolCall } from "../../types.js";
|
|
389
|
-
import type { SSEChunk } from "../types.js";
|
|
390
|
-
import {
|
|
391
|
-
splitText,
|
|
392
|
-
genId,
|
|
393
|
-
toolId,
|
|
394
|
-
shouldEmitText,
|
|
395
|
-
MS_PER_SECOND,
|
|
396
|
-
DEFAULT_USAGE,
|
|
397
|
-
} from "../serialize-helpers.js";
|
|
398
|
-
|
|
399
|
-
function buildUsage(usage: { input: number; output: number }) {
|
|
400
|
-
return {
|
|
401
|
-
input_tokens: usage.input,
|
|
402
|
-
output_tokens: usage.output,
|
|
403
|
-
total_tokens: usage.input + usage.output,
|
|
404
|
-
};
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
interface StreamBlock {
|
|
408
|
-
exec
|
|
409
|
-
/bin/zsh -lc "sed -n '1,200p' src/rule-engine.ts" in /Users/suyash.x.srijan/Documents/Personal_Projects/llm-mock-server succeeded in 0ms:
|
|
410
|
-
import type {
|
|
411
|
-
Match,
|
|
412
|
-
MatchObject,
|
|
413
|
-
MockRequest,
|
|
414
|
-
Resolver,
|
|
415
|
-
Reply,
|
|
416
|
-
ReplyOptions,
|
|
417
|
-
Rule,
|
|
418
|
-
RuleSummary,
|
|
419
|
-
} from "./types.js";
|
|
420
|
-
|
|
421
|
-
function safeRegex(re: RegExp): RegExp {
|
|
422
|
-
return re.global || re.sticky
|
|
423
|
-
? new RegExp(re.source, re.flags.replace(/[gy]/g, ""))
|
|
424
|
-
: re;
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
function compilePattern(pattern: string | RegExp): (value: string) => boolean {
|
|
428
|
-
if (typeof pattern === "string") {
|
|
429
|
-
const lower = pattern.toLowerCase();
|
|
430
|
-
|
|
431
|
-
thinking
|
|
432
|
-
**Identifying key files to locate**
|
|
433
|
-
|
|
434
|
-
I'm noting that history, loader, OpenAI serialization, and test files are needed next for a comprehensive understanding and implementation.
|
|
435
|
-
exec
|
|
436
|
-
/bin/zsh -lc "sed -n '1,200p' src/history.ts" in /Users/suyash.x.srijan/Documents/Personal_Projects/llm-mock-server succeeded in 0ms:
|
|
437
|
-
import type { MockRequest } from "./types.js";
|
|
438
|
-
|
|
439
|
-
/** A recorded request with the rule that matched and when it happened. */
|
|
440
|
-
export interface RecordedRequest {
|
|
441
|
-
readonly request: MockRequest;
|
|
442
|
-
/** The rule that matched, or `undefined` if the fallback was used. */
|
|
443
|
-
readonly rule: string | undefined;
|
|
444
|
-
readonly timestamp: number;
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
/**
|
|
448
|
-
* Records every request the server handles.
|
|
449
|
-
* Iterable and has fluent query methods for test assertions.
|
|
450
|
-
*
|
|
451
|
-
* @example
|
|
452
|
-
* ```ts
|
|
453
|
-
* expect(server.history.count()).toBe(3);
|
|
454
|
-
* expect(server.history.last()?.request.lastMessage).toBe("hello");
|
|
455
|
-
* const matched = server.history.where(r => r.rule !== undefined);
|
|
456
|
-
* ```
|
|
457
|
-
exec
|
|
458
|
-
/bin/zsh -lc "sed -n '1,200p' src/loader.ts" in /Users/suyash.x.srijan/Documents/Personal_Projects/llm-mock-server succeeded in 0ms:
|
|
459
|
-
import { readFile, readdir, stat } from "node:fs/promises";
|
|
460
|
-
import { join, extname } from "node:path";
|
|
461
|
-
import JSON5 from "json5";
|
|
462
|
-
import { z } from "zod";
|
|
463
|
-
import type { Handler, Match, MatchObject, Reply } from "./types.js";
|
|
464
|
-
import { type RuleEngine, createSequenceResolver } from "./rule-engine.js";
|
|
465
|
-
|
|
466
|
-
interface LoadContext {
|
|
467
|
-
engine: RuleEngine;
|
|
468
|
-
setFallback?: (reply: Reply) => void;
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
const json5MatchSchema = z.union([
|
|
472
|
-
z.string(),
|
|
473
|
-
z.object({
|
|
474
|
-
message: z.string().optional(),
|
|
475
|
-
model: z.string().optional(),
|
|
476
|
-
system: z.string().optional(),
|
|
477
|
-
format: z.enum(["openai", "anthropic", "responses"]).optional(),
|
|
478
|
-
}),
|
|
479
|
-
exec
|
|
480
|
-
/bin/zsh -lc "sed -n '1,200p' src/formats/openai/serialize.ts" in /Users/suyash.x.srijan/Documents/Personal_Projects/llm-mock-server succeeded in 0ms:
|
|
481
|
-
import type { ReplyObject, ReplyOptions } from "../../types.js";
|
|
482
|
-
import type { SSEChunk } from "../types.js";
|
|
483
|
-
import {
|
|
484
|
-
splitText,
|
|
485
|
-
genId,
|
|
486
|
-
toolId,
|
|
487
|
-
finishReason,
|
|
488
|
-
MS_PER_SECOND,
|
|
489
|
-
DEFAULT_USAGE,
|
|
490
|
-
} from "../serialize-helpers.js";
|
|
491
|
-
|
|
492
|
-
function buildUsage(usage: { input: number; output: number }) {
|
|
493
|
-
return {
|
|
494
|
-
prompt_tokens: usage.input,
|
|
495
|
-
completion_tokens: usage.output,
|
|
496
|
-
total_tokens: usage.input + usage.output,
|
|
497
|
-
prompt_tokens_details: { cached_tokens: 0, audio_tokens: 0 },
|
|
498
|
-
completion_tokens_details: {
|
|
499
|
-
reasoning_tokens: 0,
|
|
500
|
-
audio_tokens: 0,
|
|
501
|
-
exec
|
|
502
|
-
/bin/zsh -lc "sed -n '200,400p' src/formats/responses/serialize.ts" in /Users/suyash.x.srijan/Documents/Personal_Projects/llm-mock-server succeeded in 0ms:
|
|
503
|
-
}),
|
|
504
|
-
c({
|
|
505
|
-
type: "response.output_item.done",
|
|
506
|
-
output_index: i,
|
|
507
|
-
item: outputItem,
|
|
508
|
-
}),
|
|
509
|
-
],
|
|
510
|
-
};
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
export function serialize(
|
|
514
|
-
reply: ReplyObject,
|
|
515
|
-
model: string,
|
|
516
|
-
options: ReplyOptions = {},
|
|
517
|
-
): readonly SSEChunk[] {
|
|
518
|
-
const id = genId("resp");
|
|
519
|
-
const createdAt = Math.floor(Date.now() / MS_PER_SECOND);
|
|
520
|
-
const usage = reply.usage ?? DEFAULT_USAGE;
|
|
521
|
-
const c = createChunk();
|
|
522
|
-
let i = 0;
|
|
523
|
-
exec
|
|
524
|
-
/bin/zsh -lc "sed -n '200,400p' src/loader.ts" in /Users/suyash.x.srijan/Documents/Personal_Projects/llm-mock-server succeeded in 0ms:
|
|
525
|
-
handler.respond,
|
|
526
|
-
`(handler: ${filePath})`,
|
|
527
|
-
);
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
type FileLoader = (filePath: string, ctx: LoadContext) => Promise<void>;
|
|
532
|
-
|
|
533
|
-
const loaderByExtension: ReadonlyMap<string, FileLoader> = new Map([
|
|
534
|
-
[".json5", loadJson5File],
|
|
535
|
-
[".json", loadJson5File],
|
|
536
|
-
[".ts", loadHandlerFile],
|
|
537
|
-
[".js", loadHandlerFile],
|
|
538
|
-
[".mjs", loadHandlerFile],
|
|
539
|
-
]);
|
|
540
|
-
|
|
541
|
-
export async function loadRulesFromPath(
|
|
542
|
-
pathOrDir: string,
|
|
543
|
-
ctx: LoadContext,
|
|
544
|
-
): Promise<void> {
|
|
545
|
-
|
|
546
|
-
thinking
|
|
547
|
-
**Flagging need for tests to clarify abstractions**
|
|
548
|
-
exec
|
|
549
|
-
/bin/zsh -lc "sed -n '1,200p' test/history.test.ts" in /Users/suyash.x.srijan/Documents/Personal_Projects/llm-mock-server succeeded in 0ms:
|
|
550
|
-
import { describe, it, expect, beforeEach } from "vitest";
|
|
551
|
-
import { RequestHistory, type RecordedRequest } from "../src/history.js";
|
|
552
|
-
import { makeReq } from "./helpers/make-req.js";
|
|
553
|
-
|
|
554
|
-
describe("RequestHistory", () => {
|
|
555
|
-
let history: RequestHistory;
|
|
556
|
-
|
|
557
|
-
beforeEach(() => {
|
|
558
|
-
history = new RequestHistory();
|
|
559
|
-
});
|
|
560
|
-
|
|
561
|
-
describe("record()", () => {
|
|
562
|
-
it("adds an entry", () => {
|
|
563
|
-
history.record(makeReq(), "rule-1");
|
|
564
|
-
expect(history.count()).toBe(1);
|
|
565
|
-
});
|
|
566
|
-
|
|
567
|
-
it("adds multiple entries in order", () => {
|
|
568
|
-
history.record(makeReq({ lastMessage: "first" }), "r1");
|
|
569
|
-
history.record(makeReq({ lastMessage: "second" }), "r2");
|
|
570
|
-
exec
|
|
571
|
-
/bin/zsh -lc "sed -n '1,200p' test/mock-server.test.ts" in /Users/suyash.x.srijan/Documents/Personal_Projects/llm-mock-server succeeded in 0ms:
|
|
572
|
-
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
573
|
-
import { createMock, MockServer } from "../src/index.js";
|
|
574
|
-
|
|
575
|
-
interface OpenAIResponse {
|
|
576
|
-
choices: {
|
|
577
|
-
message: { role: string; content: string };
|
|
578
|
-
finish_reason: string;
|
|
579
|
-
}[];
|
|
580
|
-
error?: { type: string; message: string };
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
interface AnthropicResponse {
|
|
584
|
-
content: { type: string; text?: string; thinking?: string }[];
|
|
585
|
-
error?: { type: string; message: string };
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
interface ResponsesAPIResponse {
|
|
589
|
-
output: { type: string; content: { type: string; text: string }[] }[];
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
exec
|
|
593
|
-
/bin/zsh -lc "sed -n '1,200p' test/formats/openai.test.ts" in /Users/suyash.x.srijan/Documents/Personal_Projects/llm-mock-server succeeded in 0ms:
|
|
594
|
-
import { describe, it, expect } from "vitest";
|
|
595
|
-
import { openaiFormat } from "../../src/formats/openai/index.js";
|
|
596
|
-
import type {
|
|
597
|
-
OpenAIChunk,
|
|
598
|
-
OpenAIComplete,
|
|
599
|
-
OpenAIError,
|
|
600
|
-
} from "../../src/formats/openai/schema.js";
|
|
601
|
-
|
|
602
|
-
function parse<T>(chunk: { data: string }): T {
|
|
603
|
-
return JSON.parse(chunk.data) as T;
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
describe("OpenAI Format", () => {
|
|
607
|
-
describe("parseRequest", () => {
|
|
608
|
-
it("parses a basic chat completion request", () => {
|
|
609
|
-
const req = openaiFormat.parseRequest({
|
|
610
|
-
model: "gpt-5.4",
|
|
611
|
-
messages: [
|
|
612
|
-
{ role: "system", content: "You are helpful" },
|
|
613
|
-
{ role: "user", content: "Hello" },
|
|
614
|
-
exec
|
|
615
|
-
/bin/zsh -lc "sed -n '1,200p' test/formats/responses.test.ts" in /Users/suyash.x.srijan/Documents/Personal_Projects/llm-mock-server succeeded in 0ms:
|
|
616
|
-
import { describe, it, expect } from "vitest";
|
|
617
|
-
import { responsesFormat } from "../../src/formats/responses/index.js";
|
|
618
|
-
import type {
|
|
619
|
-
ResponsesEvent,
|
|
620
|
-
ResponsesComplete,
|
|
621
|
-
ResponsesError,
|
|
622
|
-
} from "../../src/formats/responses/schema.js";
|
|
623
|
-
|
|
624
|
-
function parse<T>(chunk: { data: string }): T {
|
|
625
|
-
return JSON.parse(chunk.data) as T;
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
describe("Responses Format", () => {
|
|
629
|
-
describe("parseRequest", () => {
|
|
630
|
-
it("parses string input", () => {
|
|
631
|
-
const req = responsesFormat.parseRequest({
|
|
632
|
-
model: "codex-mini",
|
|
633
|
-
input: "Hello world",
|
|
634
|
-
});
|
|
635
|
-
expect(req.format).toBe("responses");
|
|
636
|
-
exec
|
|
637
|
-
/bin/zsh -lc "sed -n '200,400p' test/formats/responses.test.ts" in /Users/suyash.x.srijan/Documents/Personal_Projects/llm-mock-server succeeded in 0ms:
|
|
638
|
-
);
|
|
639
|
-
});
|
|
640
|
-
expect(parse<ResponsesEvent>(done!).item?.status).toBe("completed");
|
|
641
|
-
});
|
|
642
|
-
|
|
643
|
-
it("includes annotations on output_text parts", () => {
|
|
644
|
-
const chunks = responsesFormat.serialize({ text: "Hello" }, "codex-mini");
|
|
645
|
-
const partAdded = chunks.find(
|
|
646
|
-
(c) => parse<ResponsesEvent>(c).type === "response.content_part.added",
|
|
647
|
-
);
|
|
648
|
-
expect(parse<ResponsesEvent>(partAdded!).part?.annotations).toEqual([]);
|
|
649
|
-
});
|
|
650
|
-
|
|
651
|
-
it("includes content_part.done event with full text", () => {
|
|
652
|
-
const chunks = responsesFormat.serialize({ text: "Hello" }, "codex-mini");
|
|
653
|
-
const partDone = chunks.find(
|
|
654
|
-
(c) => parse<ResponsesEvent>(c).type === "response.content_part.done",
|
|
655
|
-
);
|
|
656
|
-
expect(partDone).toBeDefined();
|
|
657
|
-
expect(parse<ResponsesEvent>(partDone!).part?.text).toBe("Hello");
|
|
658
|
-
|
|
659
|
-
thinking
|
|
660
|
-
**Listing additional needed tests**
|
|
661
|
-
exec
|
|
662
|
-
/bin/zsh -lc "sed -n '1,200p' test/logger.test.ts" in /Users/suyash.x.srijan/Documents/Personal_Projects/llm-mock-server succeeded in 0ms:
|
|
663
|
-
import { describe, it, expect, vi, afterEach } from "vitest";
|
|
664
|
-
import { Logger, LEVEL_PRIORITY } from "../src/logger.js";
|
|
665
|
-
import type { LogLevel } from "../src/logger.js";
|
|
666
|
-
|
|
667
|
-
afterEach(() => {
|
|
668
|
-
vi.restoreAllMocks();
|
|
669
|
-
});
|
|
670
|
-
|
|
671
|
-
describe("LEVEL_PRIORITY", () => {
|
|
672
|
-
it("has the expected keys and ascending values", () => {
|
|
673
|
-
expect(LEVEL_PRIORITY).toEqual({
|
|
674
|
-
none: 0,
|
|
675
|
-
error: 1,
|
|
676
|
-
warning: 2,
|
|
677
|
-
info: 3,
|
|
678
|
-
debug: 4,
|
|
679
|
-
all: 5,
|
|
680
|
-
});
|
|
681
|
-
});
|
|
682
|
-
|
|
683
|
-
exec
|
|
684
|
-
/bin/zsh -lc "sed -n '1,200p' test/cli-validators.test.ts" in /Users/suyash.x.srijan/Documents/Personal_Projects/llm-mock-server succeeded in 0ms:
|
|
685
|
-
import { describe, it, expect } from "vitest";
|
|
686
|
-
import {
|
|
687
|
-
parsePort,
|
|
688
|
-
parseHost,
|
|
689
|
-
parseChunkSize,
|
|
690
|
-
parseLogLevel,
|
|
691
|
-
parseLatency,
|
|
692
|
-
} from "../src/cli-validators.js";
|
|
693
|
-
|
|
694
|
-
describe("parsePort", () => {
|
|
695
|
-
it("parses a valid port", () => {
|
|
696
|
-
expect(parsePort("5555")).toBe(5555);
|
|
697
|
-
});
|
|
698
|
-
|
|
699
|
-
it("accepts port 1", () => {
|
|
700
|
-
expect(parsePort("1")).toBe(1);
|
|
701
|
-
});
|
|
702
|
-
|
|
703
|
-
it("accepts port 65535", () => {
|
|
704
|
-
expect(parsePort("65535")).toBe(65535);
|
|
705
|
-
exec
|
|
706
|
-
/bin/zsh -lc "sed -n '1,200p' test/loader.test.ts" in /Users/suyash.x.srijan/Documents/Personal_Projects/llm-mock-server succeeded in 0ms:
|
|
707
|
-
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
708
|
-
import { writeFile, mkdir, rm } from "node:fs/promises";
|
|
709
|
-
import { join } from "node:path";
|
|
710
|
-
import { RuleEngine } from "../src/rule-engine.js";
|
|
711
|
-
import { loadRulesFromPath } from "../src/loader.js";
|
|
712
|
-
import type { MockRequest } from "../src/types.js";
|
|
713
|
-
import { makeReq } from "./helpers/make-req.js";
|
|
714
|
-
|
|
715
|
-
const tmpDir = join(import.meta.dirname, ".tmp-loader-test");
|
|
716
|
-
|
|
717
|
-
describe("Loader", () => {
|
|
718
|
-
let engine: RuleEngine;
|
|
719
|
-
|
|
720
|
-
beforeEach(async () => {
|
|
721
|
-
engine = new RuleEngine();
|
|
722
|
-
await mkdir(tmpDir, { recursive: true });
|
|
723
|
-
});
|
|
724
|
-
|
|
725
|
-
afterEach(async () => {
|
|
726
|
-
await rm(tmpDir, { recursive: true, force: true });
|
|
727
|
-
exec
|
|
728
|
-
/bin/zsh -lc "sed -n '1,200p' test/formats/anthropic.test.ts" in /Users/suyash.x.srijan/Documents/Personal_Projects/llm-mock-server succeeded in 0ms:
|
|
729
|
-
import { describe, it, expect } from "vitest";
|
|
730
|
-
import { anthropicFormat } from "../../src/formats/anthropic/index.js";
|
|
731
|
-
import type {
|
|
732
|
-
AnthropicMessageStart,
|
|
733
|
-
AnthropicBlockEvent,
|
|
734
|
-
AnthropicDelta,
|
|
735
|
-
AnthropicComplete,
|
|
736
|
-
AnthropicError,
|
|
737
|
-
} from "../../src/formats/anthropic/schema.js";
|
|
738
|
-
|
|
739
|
-
function parse<T>(chunk: { data: string }): T {
|
|
740
|
-
return JSON.parse(chunk.data) as T;
|
|
741
|
-
}
|
|
742
|
-
|
|
743
|
-
describe("Anthropic Format", () => {
|
|
744
|
-
describe("parseRequest", () => {
|
|
745
|
-
it("parses messages with top-level system", () => {
|
|
746
|
-
const req = anthropicFormat.parseRequest({
|
|
747
|
-
model: "claude-sonnet-4-6",
|
|
748
|
-
system: "You are a pirate",
|
|
749
|
-
exec
|
|
750
|
-
/bin/zsh -lc "sed -n '200,400p' test/formats/anthropic.test.ts" in /Users/suyash.x.srijan/Documents/Personal_Projects/llm-mock-server succeeded in 0ms:
|
|
751
|
-
it("includes tool_use blocks with correct structure", () => {
|
|
752
|
-
const chunks = anthropicFormat.serialize(
|
|
753
|
-
{ tools: [{ name: "read_file", args: { path: "/tmp" } }] },
|
|
754
|
-
"claude-sonnet-4-6",
|
|
755
|
-
);
|
|
756
|
-
const toolStart = chunks.find((c) => {
|
|
757
|
-
if (c.event !== "content_block_start") return false;
|
|
758
|
-
return parse<AnthropicBlockEvent>(c).content_block?.type === "tool_use";
|
|
759
|
-
});
|
|
760
|
-
expect(toolStart).toBeDefined();
|
|
761
|
-
const block = parse<AnthropicBlockEvent>(toolStart!).content_block!;
|
|
762
|
-
expect(block.name).toBe("read_file");
|
|
763
|
-
expect(block.id).toBeTypeOf("string");
|
|
764
|
-
expect(block.input).toEqual({});
|
|
765
|
-
});
|
|
766
|
-
|
|
767
|
-
it("sets stop_reason to tool_use when tools present", () => {
|
|
768
|
-
const chunks = anthropicFormat.serialize(
|
|
769
|
-
{ tools: [{ name: "read_file", args: {} }] },
|
|
770
|
-
"claude-sonnet-4-6",
|
|
771
|
-
|
|
772
|
-
thinking
|
|
773
|
-
**Checking remaining mock-server tests**
|
|
774
|
-
|
|
775
|
-
Planning to review the rest of the mock-server tests to verify coverage of rule behavior before deciding if additional tests for abstractions or OpenAI are needed.
|
|
776
|
-
exec
|
|
777
|
-
/bin/zsh -lc "sed -n '200,400p' test/mock-server.test.ts" in /Users/suyash.x.srijan/Documents/Personal_Projects/llm-mock-server succeeded in 0ms:
|
|
778
|
-
|
|
779
|
-
const j1 = await postOpenAI("once");
|
|
780
|
-
expect(j1.choices[0]!.message.content).toBe("First time!");
|
|
781
|
-
|
|
782
|
-
const j2 = await postOpenAI("once");
|
|
783
|
-
expect(j2.choices[0]!.message.content).toBe("Fallback.");
|
|
784
|
-
});
|
|
785
|
-
});
|
|
786
|
-
|
|
787
|
-
describe("fallback", () => {
|
|
788
|
-
it("uses fallback when no rule matches", async () => {
|
|
789
|
-
server.fallback("I don't understand.");
|
|
790
|
-
const json = await postOpenAI("something random");
|
|
791
|
-
expect(json.choices[0]!.message.content).toBe("I don't understand.");
|
|
792
|
-
});
|
|
793
|
-
});
|
|
794
|
-
|
|
795
|
-
describe("history", () => {
|
|
796
|
-
it("records requests with matched rule info", async () => {
|
|
797
|
-
server.when("hello").reply("Hi!");
|
|
798
|
-
exec
|
|
799
|
-
/bin/zsh -lc "sed -n '400,800p' test/mock-server.test.ts" in /Users/suyash.x.srijan/Documents/Personal_Projects/llm-mock-server succeeded in 0ms:
|
|
800
|
-
describe("url property", () => {
|
|
801
|
-
it("returns the base URL", () => {
|
|
802
|
-
expect(server.url).toMatch(/^http:\/\/127\.0\.0\.1:\d+$/);
|
|
803
|
-
});
|
|
804
|
-
});
|
|
805
|
-
|
|
806
|
-
describe("error injection", () => {
|
|
807
|
-
it("nextError returns a one-shot error response", async () => {
|
|
808
|
-
server.nextError(429, "Rate limited", "rate_limit_error");
|
|
809
|
-
server.when("hello").reply("Hi!");
|
|
810
|
-
|
|
811
|
-
const r1 = await post("/v1/chat/completions", {
|
|
812
|
-
model: "gpt-5.4",
|
|
813
|
-
messages: [{ role: "user", content: "hello" }],
|
|
814
|
-
stream: false,
|
|
815
|
-
});
|
|
816
|
-
expect(r1.status).toBe(429);
|
|
817
|
-
const err = (await r1.json()) as OpenAIResponse;
|
|
818
|
-
expect(err.error?.message).toBe("Rate limited");
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
thinking
|
|
823
|
-
**Identifying abstraction duplication issues**
|
|
824
|
-
|
|
825
|
-
Noticed duplicated sequence rule-building logic between mock-server and loader/rule-engine that suggests a shared helper could reduce divergence and improve mid-level abstraction; also spotted similar buildUsage functions across serialization files hinting at potential abstraction fitness concerns.
|
|
826
|
-
thinking
|
|
827
|
-
**Scoping abstraction and elegance findings**
|
|
828
|
-
|
|
829
|
-
I've pinpointed two main abstraction issues: duplicated sequence rule construction across MockServer and loader needing a shared helper, and format endpoint lists split between MockServer and CLI risking maintenance drift; low-level code shows dense serialization logic but no critical defects, supporting moderate scores with targeted notes.
|
|
830
|
-
codex
|
|
831
|
-
{
|
|
832
|
-
"batch": "Abstractions & Dependencies",
|
|
833
|
-
"batch_index": 3,
|
|
834
|
-
"assessments": {
|
|
835
|
-
"abstraction_fitness": 82.0,
|
|
836
|
-
"mid_level_elegance": 84.0,
|
|
837
|
-
"low_level_elegance": 88.0
|
|
838
|
-
},
|
|
839
|
-
"dimension_notes": {
|
|
840
|
-
"abstraction_fitness": {
|
|
841
|
-
"evidence": [
|
|
842
|
-
"src/mock-server.ts builds sequence rules inline in when().replySequence(), including mapping entries and calling createSequenceResolver, then sets rule.remaining.",
|
|
843
|
-
"src/loader.ts repeats near-identical sequence rule wiring in addSequenceRule(), including entry mapping, createSequenceResolver, and rule.remaining."
|
|
844
|
-
],
|
|
845
|
-
"impact_scope": "module",
|
|
846
|
-
"fix_scope": "multi_file_refactor",
|
|
847
|
-
"confidence": "high",
|
|
848
|
-
"issues_preventing_higher_score": "Sequence-rule construction is duplicated in two modules, making future option/behavior changes easy to miss in one path.",
|
|
849
|
-
"sub_axes": {
|
|
850
|
-
"abstraction_leverage": 79.0,
|
|
851
|
-
"indirection_cost": 84.0,
|
|
852
|
-
"interface_honesty": 83.0
|
|
853
|
-
}
|
|
854
|
-
},
|
|
855
|
-
"mid_level_elegance": {
|
|
856
|
-
"evidence": [
|
|
857
|
-
"src/mock-server.ts registers routes from the formats array (openaiFormat/anthropicFormat/responsesFormat) and relies on each format’s route.",
|
|
858
|
-
"src/cli.ts prints a hard-coded endpoints string instead of deriving from the same formats registry."
|
|
859
|
-
],
|
|
860
|
-
"impact_scope": "module",
|
|
861
|
-
"fix_scope": "multi_file_refactor",
|
|
862
|
-
"confidence": "medium",
|
|
863
|
-
"issues_preventing_higher_score": "Endpoint listing is a manual seam between CLI output and runtime route registration, which can drift when adding/removing formats."
|
|
864
|
-
},
|
|
865
|
-
"low_level_elegance": {
|
|
866
|
-
"evidence": [
|
|
867
|
-
"src/formats/responses/serialize.ts serialize() mixes header creation, block construction, chunk flattening, and response finalization in one dense function.",
|
|
868
|
-
"src/formats/openai/serialize.ts serialize() builds text/tool chunks, finish/usage chunks, and envelopes inline without local extraction."
|
|
869
|
-
],
|
|
870
|
-
"impact_scope": "local",
|
|
871
|
-
"fix_scope": "single_edit",
|
|
872
|
-
"confidence": "medium",
|
|
873
|
-
"issues_preventing_higher_score": "Serialization functions are readable but locally dense; small extractions would make the control flow more intention-revealing."
|
|
874
|
-
}
|
|
875
|
-
},
|
|
876
|
-
"findings": [
|
|
877
|
-
{
|
|
878
|
-
"dimension": "abstraction_fitness",
|
|
879
|
-
"identifier": "sequence_rule_duplication",
|
|
880
|
-
"summary": "Sequence rule construction is duplicated across MockServer and loader, risking drift.",
|
|
881
|
-
"related_files": [
|
|
882
|
-
"src/mock-server.ts",
|
|
883
|
-
"src/loader.ts",
|
|
884
|
-
"src/rule-engine.ts"
|
|
885
|
-
],
|
|
886
|
-
"evidence": [
|
|
887
|
-
"src/mock-server.ts when().replySequence() maps entries, calls createSequenceResolver, mutates rule.resolve and rule.remaining.",
|
|
888
|
-
"src/loader.ts addSequenceRule() performs the same mapping/resolve/remaining steps with a slightly different entry shape."
|
|
889
|
-
],
|
|
890
|
-
"suggestion": "Extract a shared helper (e.g., in src/rule-engine.ts) that accepts normalized sequence steps and applies createSequenceResolver + remaining, then reuse it from both MockServer and loader.",
|
|
891
|
-
"confidence": "high",
|
|
892
|
-
"impact_scope": "module",
|
|
893
|
-
"fix_scope": "multi_file_refactor",
|
|
894
|
-
"root_cause_cluster": "sequence_rule_duplication"
|
|
895
|
-
},
|
|
896
|
-
{
|
|
897
|
-
"dimension": "mid_level_elegance",
|
|
898
|
-
"identifier": "format_registry_split",
|
|
899
|
-
"summary": "CLI hard-codes endpoints while MockServer derives routes from format modules.",
|
|
900
|
-
"related_files": [
|
|
901
|
-
"src/mock-server.ts",
|
|
902
|
-
"src/cli.ts"
|
|
903
|
-
],
|
|
904
|
-
"evidence": [
|
|
905
|
-
"src/mock-server.ts registers routes by iterating formats[] with per-format route values.",
|
|
906
|
-
"src/cli.ts prints a static endpoints list string that must be updated manually."
|
|
907
|
-
],
|
|
908
|
-
"suggestion": "Expose a single formats registry (or route list) and have the CLI render endpoints from it, avoiding cross-module drift.",
|
|
909
|
-
"confidence": "medium",
|
|
910
|
-
"impact_scope": "module",
|
|
911
|
-
"fix_scope": "multi_file_refactor"
|
|
912
|
-
}
|
|
913
|
-
],
|
|
914
|
-
"retrospective": {
|
|
915
|
-
"root_causes": [
|
|
916
|
-
"Shared logic exists without a single owning abstraction, leading to duplication across modules."
|
|
917
|
-
],
|
|
918
|
-
"likely_symptoms": [
|
|
919
|
-
"sequence_rule_duplication",
|
|
920
|
-
"format_registry_split"
|
|
921
|
-
],
|
|
922
|
-
"possible_false_positives": []
|
|
923
|
-
}
|
|
924
|
-
}
|
|
925
|
-
tokens used
|
|
926
|
-
54,720
|
|
927
|
-
|