Senior Application Developer

loc: Maynooth, ON K0L 2S0tel: 613-553-0960email: rgsamways@gmail.com
Robin Samways

$ Sreditor

A CLI tool that judges SR&ED tax-credit eligibility from a project’s own OpenSpec change history, in near real time.

## ORIGIN_STORY


I didn’t set out to build a tax-credit tool. Early in building robinsamways.ca, I started keeping a plain markdown log — docs/sreditor/ — every time I hit a genuine technical uncertainty and had to systematically work through it. Not because I had SR&ED specifically in mind yet; it was just good practice for hard problems, worth writing down while I still remembered the actual sequence of not-knowing, investigating, and resolving.

The habit paid off enough that I started paying attention to why it mattered. Canada’s SR&ED tax credit runs on a specific three-part test — a genuine technological uncertainty, a systematic investigation that resolved it, and a resulting technological advancement — assessed through Form T661 Part 2’s three word-limited lines. Roughly 60% of audited claims get denied or substantially reduced, and the gap between an approved claim and a denied one is almost never the eligibility of the underlying work. It’s the documentation. When a developer reconstructs this narrative months later, at filing time, they remember what they built, not what they didn’t know going in — producing exactly the kind of product-description language and after-the-fact-assembled claim CRA’s own denial statistics penalize.

I already had the fix, informally: a contemporaneous log, kept as I actually hit uncertainty, not reconstructed later. The only real question was whether that discipline could be automated into something a solo developer would actually keep using, instead of abandoning it the way manual note-taking usually gets abandoned once a deadline hits. Sreditor is that automation — built for real, in its own repository, across one extended session, using the same propose → implement → verify → archive discipline it exists to document.

## PROBLEMS_SREDITOR_SOLVES


Manual note-taking gets abandoned. No structure, no CRA-shaped framing, and because it’s a separate chore layered on top of actual work, inconsistently kept or dropped entirely once a deadline hits. Sreditor removes the separate-chore problem by judging each change automatically, right when it’s archived — no extra discipline required beyond already using OpenSpec.

Git history isn’t SR&ED-shaped. Commit messages are written for other developers — what changed, not what was uncertain or how it was systematically investigated. Sreditor reads proposal.md/design.md/tasks.md instead — structured reasoning a developer already writes at decision time, not reverse-engineered from commit diffs.

Reconstruction at filing time is the most expensive and least reliable option. An accountant or SR&ED consultant interviewing a developer months later reconstructs intent from memory, under time pressure — the exact failure mode behind CRA’s own denial statistics, and the developer being interviewed has usually already forgotten the real sequence of events. Sreditor’s judgment happens in near real time instead, while the sequence is still fresh.

Generic project tooling — and the funded competitors built on top of it — are still reconstruction, just automated. Jira, Azure DevOps, timesheets track work, not scientific uncertainty; tickets describe features and tasks, not hypotheses and experiments. Mining tickets, commits, and timesheets after the fact — literally how the funded competitors in this space operate — doesn’t fix the fact that it’s still reconstruction. Sreditor judges contemporaneously instead of reconstructing anything.

## SRED_ELIGIBILITY_EXAMPLE


Built across one extended session, in seven phases plus a corroborating-signals extension, each shipped through Sreditor’s own required propose → implement → verify → archive loop — the same discipline a user’s project goes through, applied to itself. As of the most recent count: 26 TypeScript source files, 1,222 non-blank lines of code, 52 passing tests across 12 test files. Every command works end to end against real Anthropic API calls, not fixtures — init, reflect, judge (with drift-auditing and corroborating signals), rollup (with a real pre-call cost estimate), report (T661-line-structured markdown with real word counts), plus scan, status, and doctor.

Two real tests, not one. Judged against its own build first: Sreditor found itself SR&ED-ineligible at every single phase — including its hardest debugging work. Then, judged against Farpost’s real, unrelated OpenSpec history — 48 archived changes, roughly four times Sreditor’s own build — it returned exactly one defensible claim. Not one easy win: a project rollup synthesized from three individually-ineligible changes (a dispatch/ranking abstraction built once around claim-to-contractor assignment, then proven to generalize to a structurally different inspection-to-inspector flow, surfacing and fixing three real hidden defects along the way). None of the three contributing changes cleared the bar judged on its own — two were rated “not close,” one “some signal” — the eligibility only became visible once rollup viewed them as one continuous investigation. Exactly one other change out of the full 48 registered above “not close” at all, and it still stayed out: the closest it came to a real technical question was resolved with a single empirical check, not a structured investigation, and CRA’s test asks for the latter. A skeptical judge that clears almost nothing, twice, on two different projects — including work it has every real incentive to find eligible in — is the calibration the entire design bet on. Not a limitation to explain away — the point, twice over.

Testing against a codebase four times Sreditor’s own size also did what dogfooding alone couldn’t: it broke things dogfooding never touched. Rollup failed outright against Farpost’s mostly-ineligible 48-change log — first an opaque parse error, then a clean token-limit error once diagnosed — because the judgment prompt asked the model to enumerate every ineligible change into its own bucket, which blew the output ceiling at that scale; fixed by having code assemble that bucket instead of the model. Rollup’s exact grouping also showed real run-to-run variance — an earlier run pulled a fourth, unrelated change into the dispatch narrative; the saved run kept it at three, same underlying story, a different boundary — worth stating plainly rather than implying the grouping is fully deterministic.

Still rough, worth naming plainly: markdown-only report output, no PDF or CSV yet. A single source adapter — OpenSpec only — though the adapter interface is designed to be tool-agnostic. Canada’s CRA SR&ED program only, not a general international R&D tax credit tool. The git-to-code correlation heuristic behind corroborating signals only sees a change’s final archiving commit, not earlier implementation commits along the way. Not yet published — npm publish and tagging v0.1.0 is the one remaining step, held back pending sign-off, not a technical blocker.

## PROCESS


Sreditor is a CLI tool, Node.js and TypeScript, that reads a project’s archived OpenSpec change artifacts — proposal.md, design.md, tasks.md, structured reasoning a developer already writes at decision time under a spec-driven workflow — and judges each one against CRA’s three-part test via a deliberately skeptical Claude (Sonnet 5) prompt, structured through zod schemas so the output is never freeform prose.

What a developer actually does: sreditor init runs a one-time AI-assisted interview that drafts a developer-authored “anchor” document — goal, genuine uncertainty, success criteria; the AI only assists in framing, never invents content, and the document is append-only once saved. From there, build normally through OpenSpec’s own propose → apply → archive loop. sreditor judge judges each newly-archived change against the three-part test, and separately compares it against the anchor for scope drift — a second, distinct model call, kept apart from the eligibility judgment specifically so one doesn’t bias the other. sreditor rollup periodically groups the accumulated judgments into CRA-shaped “projects,” the level CRA actually wants a claim framed at — gated behind a real token-cost estimate first, since it’s the one command that processes the whole accumulated log at once. sreditor report renders the rollup into T661-structured markdown, with real word counts checked against the 350/700/350 limits.

A few decisions worth naming directly, the same discipline behind this site’s own drift-audited build process: the two-layer judgment model (per-change judgment running continuously, rollup as the periodic filing-time synthesis step on top of an already-accumulated record) means the habit of thinking in SR&ED terms forms during the build, not at the end of the year. Every judgment prompt lives in the repo as plain TypeScript, readable by a developer, their accountant, or a CRA reviewer, not hidden behind a platform — transparency is the actual trust mechanism, not a slogan. Every call runs against the developer’s own Anthropic account at standard rates, no markup, no subscription — the direct structural reason a solo developer or a tiny CCPC is a market the funded, per-seat-priced competitors aren’t built to serve. Three optional corroborating-signal tools can feed extra context into a judgment prompt if installed, but are structurally barred from ever determining eligibility on their own — the prompt is explicitly instructed to treat them as non-authoritative.

Feedback on this page