Implementing sovdev-logger in a New Language
The short version, now that compare-with-master.sh exists: read the contract, study TypeScript, implement, run the comparison until it passes. No ROADMAP file to generate, no checkboxes to maintain — the comparison script is the completion gate, not a human- or model-reported checklist.
This replaces the old llm-work-templates/ 13-task system — see PLAN-003 for why, and the consolidation cleanup for why the archived scaffolding itself was later removed entirely rather than kept as a historical folder.
The process
- Read the contract, not just the prose.
01-api-contract.mdhas the exact function signatures;02-field-definitions.mdhas every log field and its type. These are the parts a model can't derive from TypeScript's code alone — the reasoning behind non-obvious cross-language decisions (e.g., "alwaysErrorforexceptionType," "always includeresponse_jsonasnull, never omit it") lives here. - Generate your field-name constants before writing any log-emitting code:
This reads the 17 field names straight frompython3 tools/codegen/generate-field-constants.py --lang {language}
schemas/log-entry-schema.json— the same source of truth01-api-contract.md/02-field-definitions.mddescribe in prose — and emits a constants module, so a typo or a stray dot in a field name becomes a compile-time/reference error instead of a silently-wrong string in the file log. If--lang {language}isn't implemented yet in the generator, add an output renderer for it first (see the existingrender_python/render_typescriptfunctions for the pattern) rather than hand-typing the 17 names — that's the exact failure mode this step exists to prevent. Exception: if your language's object/struct-literal syntax makes field names bare identifiers rather than strings (as TypeScript's does), a stray dot is already a syntax error and generated constants add less value — see PLAN-004 for why TypeScript itself doesn't consume them. Use judgment; don't skip the step without a reason as concrete as that one. - Study the reference implementation.
typescript/src/is the master — not "a" reference, the reference. When the spec and the code seem to disagree, or the spec is silent, the code wins. - Check
07-anti-patterns.mdfor the mistakes every prior implementation attempt has actually made. It's a table now, not a narrative — five minutes to read. - Set up your environment.
05-environment-configuration.mdcovers install/config;.devcontainer/additions/install-dev-{language}.shinstalls the toolchain inside the devcontainer if it isn't preinstalled. - Implement, using the generated field-name constants from step 2 instead of hand-typed field-name strings. Follow the development loop in
09-development-loop.md: edit → lint → build → run → validate logs (fast, local) → validate OTLP (slower, needs the backend) → iterate. Validate frequently in small increments, not once at the end. - Run the comparison mode until it passes:
This diffs your implementation's file-log output against TypeScript's live output for the same fixed E2E scenario (cd tools/validation/uis && ./compare-with-master.sh {language}
test/e2e/company-lookup/). Zero mismatches is the actual "done" signal — not a self-written summary. Seetools/validation/uis/README.mdfor the full verified workflow (file format → backend queries with--compare-with→ this comparison — see PLAN-001's findings on what file-log comparison can and can't catch). Note that this mode catches value/completeness bugs (wrong content, missing fields) but not the field-naming bug class step 2 already prevents by construction — the two are complementary, not redundant. - Write
{language}/README.mdonce the comparison passes, then update the rootREADME.md's status table to reflect the new "✅ Available" language — this promotion step is a required part of the language being done, not an afterthought. Diff againsttypescript/README.mdrather than duplicating its content — write only what's actually different for this language, the waypython/README.mddoes, not a second full copy of the shared essay/diagrams. Verify every code example in the new README against the actual public API before publishing it; run the quickstart example for real.
Known blind spots
compare-with-master.sh only covers file-log JSON for one fixed scenario. It does not check OTLP wire payloads, metrics, or Grafana rendering — confirmed empirically that 2 of the 3 historically-documented Python bugs (metric naming, OTLP-only timestamp) never touch the file log at all and would not be caught by this alone. For those, use tools/validation/uis/query-loki.sh/query-tempo.sh/query-prometheus.sh with --compare-with against the live backend (requires kubectl access to the local UIS cluster), or tools/validation/grafana-cloud/ if you're validating against a real Grafana Cloud backend instead (no kubectl needed there — HTTP Basic Auth).