Hourly @ $60/hr, invoiced against the existing Viatika engagement. No fixed cap. One line per session. Append-only.
Format: YYYY-MM-DD | HH:MM–HH:MM | X.Xh | summary
- 2026-04-15 | 10:30–12:00 | 1.5h | Kickoff. Drafted
BRIEF.md,SPEC.mdv0.0.1,CONTRACT.md. Initial scoping draft right-sized to a 10h / $600 fixed bid framing at Lanzafame's request. - 2026-04-15 | 13:15–13:45 | 0.5h | SPEC amendment: added §3.1 citation types (extension point) with VDS (Verified Data Session) as the first non-
sourcetype, referencing DerbyFish BHRV as the reference implementation. Zero-cost forward-compatibility hook. - 2026-04-18 | 13:10–13:46 | 0.6h | Session 3. Reframed billing from fixed-bid to hourly. Rewrote
BRIEF.md+CONTRACT.md(author=Gian, open source, no ownership transfer). PolishedSPEC.mdto v0.1 (addedspec+citation_typesto manifest, error codes, graceful-degrade rule). Addedpackage.json,tsconfig.json,types.ts,server.ts(Hono, 3 tiers, in-memory corpus, stub payment verification),agent.ts(discovery → 402 → paid envelope → insight tier),demo.sh,README.md.npm install+tsc --noEmitclean. End-to-end flow verified: server boots, manifest served, 402 challenge emitted, paid envelope returns withsourcecitation + receipt, insight tier returns NL summary. Local-only, no git remote. Next: plug in real x402 facilitator verification, swap in-memory corpus for a real upstream, decide repo home. - 2026-04-19 | TBD | TBDh | Session 4. Bumped
SPEC.mdto v0.2 (backwards-compatible): added §4 optionalindexmanifest (type, model, dim, distance, chunks, chunk_strategy, corpus_sha256, built_at) so merchants declare retrieval scheme, and §3.2 optionalchunk_id+retrieval.{model, score, rank}on source citations so citations are reproducible, not just referenceable. Extendedtypes.ts(IndexManifest, RetrievalProvenance, ChunkStrategy, IndexType, ChunkKind, SPEC_VERSION="feed402/0.2"). UpdatedREADME.mdwith "What's new in v0.2" section + fifth bullet in the 60-second pitch on retrieval reproducibility. All additions optional; v0.1 servers remain compliant under v0.2 per §2.3 unknown-field rule. Server not yet updated to emit v0.2 manifest (queued for next session). - 2026-04-21 | TBD | TBDh | Session 5. Brought
server.tsto v0.2 parity: emitsspec: "feed402/0.2", includes §4indexblock (sparse matcher,corpus_sha256computed at boot from CORPUS), attaches §3.2chunk_id+retrieval.{model,score,rank}on insight-tier citations and on query-tier citations whencontainssubstring retrieval runs (year-only structured filter correctly omits both per "providers that do not do retrieval SHOULD omit"). AddedcomputeCorpusHash,substringScore,chunkIdOfhelpers (~60 LOC). ExtendedsourceCitationto optionally carry retrieval provenance. Bumped agent.ts to print manifestindexblock and citation retrieval fields sodemo.shvisibly shows v0.2 output.tsc --noEmitclean, demo passes end-to-end, wire-level manifest + all four envelope shapes (manifest, raw, query-with/without-retrieval, insight) verified via curl. Rewrotescripts/send-to-lanzafame.sh: replaced stale fixed-bid packet framing with short hourly-era resync (v0.2 summary + three steering questions: protocol direction / repo home / next burn target). Still local-only, no git remote. - 2026-04-21 | TBD | TBDh | Session 7 (both repos; post repo-split to gianyrox/*). Punch list #2-#6 completed end-to-end. Gateway #2 (real tx hash): refactored async-settle goroutine into
settleWithTimeout(bounded 3s synchronous wait, background-continuation on timeout,extractSettleTxHashaccepts transaction|txHash|tx_hash|tx and rejects success=false) so receipt.tx is now a real on-chain reference from Base, with gracefulpending:<hash>fallback when the facilitator is slow. Gateway #3 (per-hit citations): newhit_parsers.gowith pluggablehitParserregistry keyed by route.ID — PubMed ESearch, Semantic Scholar Graph, OpenAlex /works (+ URL-tail extraction), ClinicalTrials v2. Added optionalhits []feed402Hit(source_id + canonical_url + rank) on the envelope (v0.2-additive per SPEC §2.3). Capped at 10 hits per call. TS #4 (real Kruse + OpenAI): shipped 4 new files (embedder.ts— narrow interface +OpenAIEmbedderfor text-embedding-3-small +MockEmbedderfor offline;corpus.ts— 460-post Kruse loader with 350-word chunks / 50-word overlap + stablecorpusFingerprint;index-store.ts— single-file JSON dense vector store withsaveIndex/loadIndex/topK;build-index.ts— one-shot CLInpm run build-index, batches 100, backoff, ~$0.04 for full corpus).server.tsnow loads dense index on boot and promotes /insight to real cosine top-5 retrieval with chunk_id + retrieval provenance in the citation, falls back to the 3-paper sparse demo when no index file exists (backwards-compat). Smoke-tested end-to-end with mock embedder on 5 posts (11 chunks): manifest §4 showstype=dense, model=mock:sha256-128, dim=128, corpus_sha256=..., /insight 402s unpaid, returns full envelope with per-hit provenance when paid. TS #6 (viem real x402): replacedstubPaymentHeaderwithrealPaymentHeader— viem-backed EIP-3009 transferWithAuthorization signing against the USDC domain (USD Coin/v2/chainId=manifest.chain/verifyingContract=USDC, canonical addresses for base + base-sepolia baked in), 60s auth window, random 32-byte nonce, packages v2 x402 envelope ({x402Version, payload: {authorization, signature}, accepted: {scheme,network,asset,amount,payTo,maxTimeoutSeconds,extra}}); gated byFEED402_AGENT_PRIVATE_KEYenv so stub remains the cold-boot default. Verified real-signing path end-to-end against reference server with a dev key. Gateway #5 (insight tier): newinternal/handler/insight.go(~270 LOC) +InsightConfigon Feed402Config. Synthetic/research/insightroute auto-appended to cfg.Routes on boot so manifest + x402 SDK + routeIndex see it uniformly. ExtracteddecodeAndVerifyPaymentfromhandlePaymentAndProxy(now 3 lines) — shared by both paths, cleaner. Flow: verify+settle →cloneForRetrievalfills every PassThrough param + common aliases (term/query/q/search) with the question → in-processproxyToUpstreamto configuredretrievalRouteId→extractSnippetswalks the upstream JSON pulling ≥40-char string fields (captures title/abstract/description/summary across all 4 recognized upstreams without per-upstream parsers) up tomaxContextChars→ summarizer (mockSummarizer default, openAISummarizer against /v1/chat/completions with anti-fabrication system prompt when OPENAI_API_KEY set) → envelope with top-hit as primary §3 citation + §3.2 retrieval provenance {model=summarizer.id()} + v0.2-additive hits array + receipt tier=insight. Added §3.2 fields (chunk_id,retrieval) tofeed402CitationSourcestruct — gateway envelope surface now matches full SPEC §3.2 shape. 3 new Go tests (mockSummarizer determinism + empty-context fallback; extractSnippets nested-JSON walk + maxChars cap; buildInsightCitation top-hit promotion + no-hits synthetic fallback). Tally: 11 handler tests green,go build ./...+go vetclean,tsc --noEmitclean on the TS side. 6 commits total acrossgianyrox/x402-research-gatewayandgianyrox/feed402. This closes the punch list kicked off at start of session. - 2026-04-21 | TBD | TBDh | Session 6 (sibling repo:
~/freelance/x402-research-gateway). Brought the production-ish Go research gateway to feed402/0.2 protocol compliance — the second live merchant, which is the actual "protocol travels" proof. Extendedinternal/config/config.go: added top-levelFeed402Config(enabled, name, version, spec, citationPolicy, contact), per-routeFeed402Tier("raw"|"query"|"insight", validated), andRouteCitation(sourcePrefix, canonicalUrlTemplate, providerUrl, license). Fixed pre-existing loader bug:os.ExpandEnvdoesn't understand bash-style${VAR:-default}syntax (was silently nuking${KRUSE_SEARCH_URL:-http://localhost:8765}to empty and failing validation); addedexpandEnvWithDefaultspreprocessor (regex-based, falls through to stdlib expand for${VAR}). Createdinternal/handler/feed402.go(~240 LOC): Manifest types mirroring SPEC §1+§4, envelope types mirroring SPEC §3,buildFeed402Manifest()generating discovery from config (cheapest-per-tier canonical + fullroutes+tier_routesaggregates),handleFeed402Manifestserving/.well-known/feed402.json(free, 60s cache),wrapFeed402Envelopewrapping upstream bodies in the §3 envelope (JSON passed asjson.RawMessage, non-JSON stringified),buildCitationForresolving per-route source_id (canonical URL template with passthrough-param substitution for id-bearing routes, syntheticprefix:query:<sha256-trunc>for search routes), placeholderpending:<hash>tx when async settle. Wired the manifest route into the chi router (only whenFeed402.Enabled) + wrapped upstream responses on 2xx after successful facilitator verify; legacy error-body passthrough preserved. Tagged all 7 live routes inconfig/routes.yamlwith tier + citation config: pubmed-search (query, public-domain), pubmed-fetch (raw, canonical templatehttps://pubmed.ncbi.nlm.nih.gov/{id}/), semantic-scholar-search (query, CC-BY-NC-4.0), openalex-works (query, CC0), clinicaltrials-search (query, public-domain), kruse-search (query, citation-only), pubchem-compound (raw, template with {name}). Addedinternal/handler/feed402_test.go(~180 LOC, 5 tests all green): manifest shape + cheapest-per-tier selection, envelope shape for search tier (synthetic source_id), envelope shape for raw tier (canonical URL template substitution), non-JSON body stringification (PubMed XML case), price parsing.go build ./...clean. Live wire test: booted gateway on :8092, confirmed/.well-known/feed402.jsonserves the full v0.2 manifest with all 7 routes,/research/pubmed/searchwithout payment returns properHTTP 402 Payment Requiredwith x402 challenge header in base64. Gateway is now the second feed402 merchant (first = the TypeScript reference atserver.tswith fake in-memory corpus; second = this gateway with 7 real upstream research APIs). Two merchants = a pattern; the protocol now visibly travels.
Hour reconciliation note (2026-04-21): The logged session durations (1.5 + 0.5 + 0.6 = 2.6h through session 3) understate actual burn. Sessions 4 and 5 are intentionally logged with TBDh pending reconciliation; earlier sessions may also be under-logged. Before the next invoice roll-up into the parent Viatika engagement, backfill real hours from editor / terminal / commit timestamps and replace the TBD entries in place.