Repository navigation
Port preprint-af exactly to native Go - #1
Merged
Merged
Conversation
santoshkumarradha
marked this pull request as ready for review
August 4, 2026 18:29
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
The port declared every `str | None` reasoner parameter as `{"type":"object"}`.
The Python SDK resolves annotations with `typing.get_type_hints`, which turns
PEP-604 `str | None` into `typing.Optional[str]`, so `_type_to_json_schema`
unwraps it and publishes `{"type":"string"}` (agent.py `_type_to_json_schema`).
`target_venue`, `field_hint` and every `model` argument were therefore advertised
with the wrong type; `examples/payload.json` does not validate against the
published `write_paper` schema.
Also restores four node-level behaviours the Python app had:
- `HarnessConfig` model falls back to DEFAULT_MODEL, not to `AI_MODEL`, so an
`AI_MODEL` override no longer silently retargets the OpenCode workers.
- DID and VC generation are on: the Python `Agent` constructor defaults
`enable_did=True` and `vc_enabled=True`.
- OpenCode concurrency (10) and harness timeout (1800s) match the Python
provider defaults instead of the Go SDK's lower ones.
- Reasoner descriptions carry the Python docstring summary rather than a
generated "Exact Go port of ..." string, and the entry point's tags keep
Python's router-then-decorator order (`workflow`, `entry`).
Tests cover `Build()+RegisterAll()` with and without an API key (an unknown
name makes `reasonerInputSchema` panic at startup), the full registered
surface, and `examples/payload.json` against the published schema.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Divergences found by diffing each Go reasoner body against the Python one it replaces: - Truncation counted bytes where Python counts code points, so any non-ASCII paper silently got a shorter evidence/paper excerpt than the prompts promise. - `STATE.json` was written with Go's encoder; Python writes `json.dumps(indent=2)`, which escapes non-ASCII and leaves `<>&` literal. - Structured-output schemas were strictified for both paths. Python only strictifies the direct `.ai` response_format (`_strictify_openai_schema`); the harness path passes the plain Pydantic schema, so defaulted fields must stay optional there. - Filesystem write failures (BLUEPRINT.md, main.tex, round artifacts, REVIEW.md, STATE.json) were dropped, reporting a successful run that had written nothing. - Context cancellation was converted into a model fallback, so a cancelled run kept producing neutral reviews and "repairs" instead of stopping. - `RunLatexmk` raced: the timeout goroutine wrote `timedOut` while the main goroutine read it. Replaced with `exec.CommandContext`. - `round4` did not match Python's `round(v, 4)`: scaling by 10000 first double-rounds, so `round(0.00005, 4)` is 0.0001 in CPython but 0.0 in Go. It now rounds through `strconv.FormatFloat`, which is correctly rounded with ties-to-even on the exact binary value like CPython. - Repair-plan digest bytes, target resolution order (`global` after an exact glob), the synthesized section glob, `~` expansion in `folder_path`, Markdown `True`/`False` spelling, and positioning artifact ordering all differed. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- The fidelity auditor does not "fail the build"; it blocks quality-threshold convergence, and plateau / no-repair / safety-cap stops are still terminal. - The compile gate requires a zero `latexmk` exit, so a run that stops on a plateau can return an empty `pdf_path`. - `plateau_delta` is a documented `write_paper` parameter but was missing from the parameter table. - Model strings are OpenRouter ids; the Go node has no LiteLLM routing. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Python's `scan_novelty` wraps the OpenCode call in `try/except Exception` and returns `safe_ai_fallback(NoveltyScan)` (positioning.py:226-235): the literature scout is advisory, so a crashed or unavailable harness must not take positioning with it. The Go port returned the harness error, which fails `positioning_run_positioning` and therefore the whole `write_paper` run. Cancellation still propagates — `except Exception` does not catch `asyncio.CancelledError` — so only non-cancellation failures degrade. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- Fidelity overlay: Python snapshots `result.citation_issues` before appending
its deterministic findings (`flagged = {c for c in result.citation_issues}`,
critique.py:242). Go re-scanned the growing slice, so a finding for
`\cite{smith2024}` suppressed the finding for `\cite{smith}` — the repair
planner was never told about the second missing key.
- `TODO.md`: Python's `append_todos` is a synchronous helper with no `await`,
so the event loop cannot interleave two appends. Go runs the figure workers
on real goroutines, where two unbuildable figures could each read the old
file and the later write dropped the other's bullet. Serialised with a mutex.
- Blueprint title fallback: Python strips a `title:` prefix case-insensitively
(`title.lower().startswith("title:")`, blueprint.py:43), so a `## TITLE: X`
heading yields `X`; Go only stripped the exact spelling `Title:`.
- `TestDirectAISchemaUsesPythonStrictResponseContract` asserted Go's sorted
`required` order and called it Python parity. JSON Schema treats `required`
as a set and Python emits declaration order, so the test now asserts the
member set and says so.
Each of the first three has a regression test that fails against the previous
code.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
`main` carried a `ci.yml` that byte-compiled `main.py` and the reasoner package and asserted a few helpers (removed in 3a0d5d2 because it had gone stale). This PR deletes everything that gate covered, so the repo would land a 5k-line rewrite with no automated verification at all. This is the same shape of gate for the Go tree: build, vet, test. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Contributor
|
Took this over since it had been sitting for ~7 weeks. No rebase was needed — the branch was still on top of The ones worth knowing about:
Two things I left for you:
Not verified here: the Docker image build, registration against a live control plane, and a real LaTeX run — no Docker/WSL integration, no OpenRouter key, no TeX on this box. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
docker compose up --buildpath launch the Go nodeartifacts/deepseek-v4-flash/preprint-af-go.pdfWhy
The earlier Go implementation had drifted from the Python behavior and the repository shipped two runtime paths. This branch restores byte-level prompt and schema parity, preserves the dynamic AgentField call graph, verifies the complete pipeline, and then removes the duplicate Python node so there is one production implementation.
Python remains in the container only as the execution runtime for generated Matplotlib figure scripts. It is not an AgentField node.
Validation
go test ./...go vet ./...docker compose config --quietgit diff --check