Merge pull request #1 from Mihir-Null/claude/miterm-redesign-cleanup-vhd49u

Add resume.org SSOT + org→json pipeline (redesign phase 1)
pull/59/head
Mihir Talati 3 weeks ago committed by GitHub
commit 82ac784148
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,20 @@
# Drift canary for the résumé declared mirror (praxis: Mirrors and Canaries).
# Fails if resume.json is out of sync with its canonical source resume.org.
name: resume-canary
on:
push:
paths: ['resume.org', 'resume.json', 'scripts/org-to-json.mjs']
pull_request:
paths: ['resume.org', 'resume.json', 'scripts/org-to-json.mjs']
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- name: Verify resume.json matches resume.org
run: node scripts/org-to-json.mjs resume.org resume.json --check

@ -0,0 +1,68 @@
:PROPERTIES:
:ID: 77df5ef7-abf4-416f-a0fa-82119ab40e66
:END:
#+TITLE: ADR 0001 — MiTerm Redesign: Source, Pipeline, Topology, Minimalism
#+FILETAGS: :adr:miterm:
Status: accepted (2026-07-16)
Deciders: Mihir Talati (navigator), agent (driver)
Bundled MADR-style record for the four load-bearing decisions that open the
MiTerm redesign. Praxis references point at the canonical praxis graph
(Emacs-Vault, refactor-v2 branch).
* Context
MiTerm (the terminal résumé site) and its GitHub Pages deployment had drifted
into two full, diverging Next.js apps, with résumé content duplicated between
~content.json~ (terminal) and a hand-written ~public/resume.html~ (plain page).
CRT effects, a dead login overlay, and a per-second clock had accrued. Goal:
return to a clean, minimal LiveTerm-like terminal usable by technical managers
and non-technical recruiters, with a single, extensible authoring backend.
* Decision 1 — Canonical résumé source: one ~resume.org~ in the site repo
Author the résumé as a single Org file, structured as org-roam nodes (one
~:ID:~ heading per item). It is the Single Source of Truth; ~resume.json~ is a
generated, declared mirror consumed by both the terminal and the plain page.
- Alternatives: org-roam nodes inside the Emacs-Vault graph (rejected now:
couples the public build to a private repo — deferred, see Consequences);
keep editing ~content.json~ (rejected: no org authoring, weak SSOT).
- Praxis: Single Source of Truth; Homoiconicity / Text Is the System;
Declared Mirrors.
* Decision 2 — Build pipeline: standalone Node parser, no Emacs in CI
~scripts/org-to-json.mjs~ parses ~resume.org~~resume.json~ as a prebuild
step. Flow is one-way; a ~--check~ canary (regenerate + diff) fails CI on drift.
- Alternatives: Emacs batch export (rejected: Emacs dependency in CI, slower);
manual local export (rejected: mirror silently drifts).
- New Code Is a Liability: mature JS org parsers (~orga~, ~uniorg~) were
considered and rejected because the schema is small and self-owned — a
dependency tree would be more liability than a ~120-line contract-first
reader. Divergence from the consensus "use a library" default is deliberate
and recorded here.
- Praxis: Contract-First Modules; Tangle Discipline; Mirrors and Canaries.
* Decision 3 — Repo topology: MiTerm canonical, github.io = build output
MiTerm holds all source (app, ~resume.org~, parser, config). The static export
is published to ~Mihir-Null.github.io~, which serves GitHub Pages (CNAME
nullis.me) and holds build output only.
- Alternatives: github.io canonical, retire MiTerm (rejected: contradicts the
"MiTerm deploys to github.io" model); keep both apps sharing JSON (rejected:
maximum duplication).
- Consequence: cross-repo publish needs a deploy token/PAT secret — tracked as
the one operational dependency, wired in the deploy phase.
* Decision 4 — Minimalism scope
Remove: all CRT effects (barrel-distortion generator, ~crt~ command,
warp/curve, CRT CSS); the dead ~.login-*~ overlay CSS; the per-second age/clock
ticker (render once, statically). Reduce ~ls~/~sumfetch~ from boxed widgets to
flat text — tree as the default listing — while keeping hover highlighting and
clickable elements. Keep the joke and web-search commands (low cost, personality).
- Praxis: New Code Is a Liability (delete before adding); Atomicity.
* Consequences
- ~resume.org~ Profile is the canonical home for name/contact facts;
~config.json~'s duplicate identity fields are slated for removal in the
wiring phase so there is one home (SSOT). Until then the overlap is a
declared, temporary mirror.
- Indexing ~resume.org~ into the Emacs-Vault org-roam graph later stays open
via multi-directory org-roam or ~:ROAM_REFS:~ — no lock-in from Decision 1.

@ -0,0 +1,49 @@
:PROPERTIES:
:ID: 1592cfdd-398a-4604-a843-eed9d0f7d1bb
:END:
#+TITLE: Résumé Pipeline (Reference)
#+FILETAGS: :miterm:reference:
Diátaxis: reference. How résumé content flows from authoring to the rendered
site. See [[file:decisions/0001-miterm-redesign-decisions.org][ADR 0001]] for why.
* Data flow
#+begin_example
resume.org canonical source (you edit ONLY this)
│ node scripts/org-to-json.mjs resume.org resume.json (one-way, prebuild)
resume.json declared mirror — generated, never hand-edited
├─► terminal ls / sumfetch / summary read resume.json
└─► resume.html plain page reads resume.json
│ next build && export
docs/ (github.io) build output — GitHub Pages, CNAME nullis.me
#+end_example
* Mirror table (praxis: Mirrors and Canaries)
| Fact | Canonical home | Mirror(s) | Canary |
|------------------------------+-----------------------+------------------+--------------------------------|
| résumé content + profile | resume.org | resume.json | ~yarn resume:check~ (regen+diff) |
| rendered terminal / plain | resume.json | DOM at runtime | build reads mirror, no copy |
A mirror without a canary is a defect. ~resume.json~'s canary is the
~--check~ mode of the parser, run in CI and before build.
* How to edit the résumé
1. Edit ~resume.org~. To add an item, copy an item heading, mint a fresh
~:ID:~ (~org-id-get-create~ or ~uuidgen~), fill the drawer + bullets.
2. Run ~yarn resume:build~ (or just ~yarn dev~ / ~yarn build~ — it runs first).
3. Commit ~resume.org~ *and* the regenerated ~resume.json~ together, so the
canonical change and its mirror land in one commit.
* Schema (RESUME_SCHEMA: 1)
- ~* Section~ headings: Profile, Experience, Projects, Education,
Organizations, Publications, Skills.
- ~** Item~ headings carry an ~:ID:~ and typed scalar fields in a drawer.
- ~- bullet~ → the item's ~bullets~ array.
- ~- tag :: value~ → named arrays; Education uses ~degree~, ~honor~, ~course~.
- Profile: drawer → identity fields; prose body → ~bio~.
- Skills: ~** Category~ headings; bullets → that category's list.
The parser contract lives at the top of ~scripts/org-to-json.mjs~.

@ -8,6 +8,10 @@
"email": "contact@wensenwu.com"
},
"scripts": {
"resume:build": "node scripts/org-to-json.mjs resume.org resume.json",
"resume:check": "node scripts/org-to-json.mjs resume.org resume.json --check",
"prebuild": "yarn resume:build",
"predev": "yarn resume:build",
"dev": "next dev",
"build": "next build",
"start": "next start",

@ -0,0 +1,230 @@
{
"$generated": "GENERATED FILE — do not edit. Source of truth: resume.org. Regenerate: node scripts/org-to-json.mjs",
"profile": {
"name": "Mihir Talati",
"github": "Mihir-Null",
"linkedin": "mihir-talati-2671a2247",
"email": "mihirtalati3@gmail.com",
"phone": "(240)-351-1014",
"citizenship": "US",
"bio": "Pursuing dual degrees in Computer Science and Physics at the University of Maryland. Exploring quantum computing, machine learning, and physics based simulation with an emphasis on research and development. Interested in all things science and technology. Hobbies include tinkering with unix and hardware, game development and literature."
},
"experience": [
{
"id": "809dd6f7-7700-43ae-ac87-ae2ec79ab4ef",
"role": "Researcher",
"company": "CAAR REU (QuICS)",
"dates": "Jun 2025 Aug 2025",
"bullets": [
"Created families of fault-tolerant CSS quantum error-correcting codes for qudits.",
"Proved transversal Clifford and T gate support using finite field and QEC theory.",
"Built parallel Python tooling (Galois, NumPy, Magma, SageMath) to test self-orthogonality and distance."
]
},
{
"id": "4ee96812-4a42-4fce-ab41-223dc3237ed1",
"role": "Undergraduate Researcher",
"company": "Bright Beams Collective (IREAP)",
"dates": "Sep 2023 Dec 2024",
"bullets": [
"Designed machine learning and gradient optimizers for particle accelerator beamline tuning.",
"Ran MAD-X and Elegant simulations to evaluate lattice stability and beam quality.",
"Produced Fusion 360 and Ansys visualizations for educational and technical presentations."
]
},
{
"id": "9ca345ca-c318-4d70-aa4d-8542bc322589",
"role": "Software Engineering Intern",
"company": "JODO PAY",
"dates": "Jun 2022 Jul 2022",
"bullets": [
"Automated invoice generation and delivery via Google Workspace APIs.",
"Reduced manual processing by approximately 40 staff hours each week.",
"Hardened error handling and template management with TypeScript and Apps Script."
]
}
],
"projects": [
{
"id": "28f564fa-8ac8-4720-bf5c-cf999186cf6d",
"name": "Quantum State Tomography via QML",
"timeline": "Sep 2024 Jul 2025",
"bullets": [
"Co-developed variational circuit tomography with custom losses and embeddings.",
"Launched 2,000+ experiments across multi-GPU clusters via bespoke orchestration tools.",
"Co-author on \"Quantum state reconstruction with variational quantum circuit\" (arXiv:2507.01246)."
]
},
{
"id": "25c4d9b7-ea24-4af7-8cac-f1855743abc6",
"name": "MIT iQuHack — QuEra Challenge",
"timeline": "Feb 2025",
"bullets": [
"Built a compilation pipeline translating QAOA and error-correcting circuits into neutral atom instructions.",
"Optimized pulse schedules using Qiskit, Cirq, Bloqade, PyTorch, and TensorFlow Quantum.",
"Team earned an Honorable Mention from QuEra."
]
},
{
"id": "e00b83aa-277b-4379-96aa-989754fefbcb",
"name": "Club Administration Automation",
"timeline": "Nov 2024 Feb 2025",
"bullets": [
"Automated Discord announcements, email campaigns, Instagram posts, and room reservations.",
"Integrated Google APIs, Discord.py, Selenium, and OAuth2 for end-to-end workflows.",
"Adopted by multiple university clubs to reduce administrative effort."
]
},
{
"id": "5a0897f1-4b2c-4dd4-a68e-8a324822f425",
"name": "Quantum ML Research Collection",
"timeline": "Aug 2023 Dec 2024",
"bullets": [
"Crafted quantum image processing pipelines with parameterized kernels inside CNNs.",
"Designed a hybrid transitional optimizer that mitigates barren plateaus in QAOA.",
"Presented findings at the 2024 First Year Innovation & Research Experience Summit."
]
},
{
"id": "25053703-72e2-492d-bf8b-4a5953b6160e",
"name": "Housing Market Analysis",
"timeline": "Jun 2024 Jul 2024",
"bullets": [
"Built feedforward neural networks to predict housing prices from public datasets.",
"Applied PCA and statistical analysis to surface high-signal features.",
"Combined web-scraped listings with census data to improve model robustness."
]
},
{
"id": "bdf83287-24aa-4f55-9a07-e11d6e08e319",
"name": "Indie Game Development",
"timeline": "2020 2023",
"bullets": [
"Shipped two action platformers with custom soft-body simulation via Unity/Unreal.",
"2nd place, 2021 Mindbox National Design Championship (Game Design).",
"National finalist, 2020 Mindbox Design Championship (Game Development).",
"Authored a procedural map generation toolkit for arbitrary tilemaps."
]
}
],
"education": [
{
"id": "86d31d81-d7e2-4035-9441-54badb1724a7",
"school": "University of Maryland — College Park",
"gpa": "3.974",
"graduation": "May 2027",
"degrees": [
"B.S. Computer Science (Honors)",
"B.S. Physics (Honors)"
],
"honors": [
"Angelo Bardasis Scholarship — Physics",
"John D. Gannon Scholarship — Computer Science",
"Dean's List — Every Semester"
],
"coursework": [
"Graduate Quantum Computing (CMSC657)",
"Differentiable Programming for Agentic AI (CMSC498Z)",
"Natural Language Processing (CMSC470)",
"Data Science (CMSC320)",
"Design & Analysis of Algorithms (CMSC451)",
"Honors Advanced Modern Physics (PHYS400)",
"Quantum Mechanics II (PHYS402)"
]
}
],
"organizations": [
{
"id": "9ed6f6b0-5389-485f-aa00-e6c934737e3d",
"role": "Industry Chair",
"org": "Quantum Coalition",
"dates": "Jan 2024 Present",
"bullets": [
"Co-organized the QRISE research competition with 200+ global participants.",
"Partnered with the UN and ITU to deliver the QC-FLIQ hackathon (500+ attendees)."
]
},
{
"id": "c458048e-95be-4726-9345-b4af7650ba4d",
"role": "President",
"org": "Undergraduate Quantum Association",
"dates": "Jan 2025 Present",
"bullets": [
"Led programming, partnerships, and outreach after four years as an officer.",
"Hosted the Quantum Leap Career Nexus with 240+ attendees across IBM, Microsoft, Amazon Braket, IonQ, and more."
]
},
{
"id": "145dbb0c-cf88-46e0-bc3e-052120e83978",
"role": "Co-President",
"org": "ACM@UMD",
"dates": "Sep 2023 Present",
"bullets": [
"Restarted the official student chapter and launched a new web presence.",
"Grew membership to 145+ students with workshops on shell scripting, AI, and quantum computing."
]
}
],
"publications": [
{
"id": "0f86c17a-6165-4b78-9610-5d6cb3da2977",
"title": "Quantum state reconstruction with variational quantum circuit",
"status": "Preprint — arXiv:2507.01246",
"bullets": [
"Introduces a quantum machine learning approach to tomography for high-dimensional states.",
"Benchmarks loss landscapes, embedding strategies, and optimizer behavior across noise models.",
"Highlights scalability results enabled by custom experiment orchestration."
]
},
{
"id": "e7c3273b-0c2b-43d4-94fc-fca989893799",
"title": "A Very Quick Guide to Special Relativity",
"status": "Published — 2021",
"bullets": [
"Wrote and published an accessible primer covering time dilation through mass-energy equivalence.",
"Focused on first-principles explanations for students exploring modern physics."
]
}
],
"skills": {
"languages": [
"Python",
"C",
"C++",
"JavaScript/TypeScript",
"Rust (learning)"
],
"quantum": [
"Qiskit",
"Cirq",
"PennyLane",
"Q#",
"Bloqade"
],
"ml": [
"PyTorch",
"TensorFlow Quantum",
"NumPy",
"SciPy",
"scikit-learn",
"MPI",
"Numba"
],
"simulation": [
"MAD-X",
"Elegant",
"Magma",
"SageMath",
"Fusion 360",
"Ansys Workbench"
],
"tools": [
"Git",
"Docker",
"Google Cloud APIs",
"Selenium",
"Discord.py",
"REST APIs"
]
}
}

@ -0,0 +1,252 @@
:PROPERTIES:
:ID: 9e39c816-2584-4004-a47d-d12edd3ed346
:RESUME_SCHEMA: 1
:END:
#+TITLE: Mihir Talati — Résumé (Canonical Source)
#+FILETAGS: :resume:
# ============================================================================
# CANONICAL RESUME SOURCE — SINGLE SOURCE OF TRUTH
#
# This file is the one authoritative home for every résumé fact. The terminal
# (ls / sumfetch / summary) and the plain résumé page both read `resume.json`,
# which is a DECLARED MIRROR generated from this file by:
#
# node scripts/org-to-json.mjs resume.org resume.json
#
# Flow is one-way: org -> json. Never hand-edit resume.json; edit THIS file and
# regenerate. CI re-runs the parser and fails on any diff (the canary).
#
# SCHEMA the parser expects (RESUME_SCHEMA: 1):
# * Section top-level headings name the sections below.
# ** Item each item is a roam node: it carries its own :ID: and
# typed scalar fields in a :PROPERTIES: drawer.
# - bullet plain list items become the item's `bullets` array.
# - tag :: value tagged bullets route into named arrays (education uses
# `degree`, `honor`, `course`).
# Add a new experience/project/etc. by copying an item heading, minting a fresh
# :ID: (`org-id-get-create` in Emacs, or `uuidgen`), and filling the drawer.
# ============================================================================
* Profile
:PROPERTIES:
:NAME: Mihir Talati
:GITHUB: Mihir-Null
:LINKEDIN: mihir-talati-2671a2247
:EMAIL: mihirtalati3@gmail.com
:PHONE: (240)-351-1014
:CITIZENSHIP: US
:END:
Pursuing dual degrees in Computer Science and Physics at the University of
Maryland. Exploring quantum computing, machine learning, and physics based
simulation with an emphasis on research and development. Interested in all
things science and technology. Hobbies include tinkering with unix and
hardware, game development and literature.
* Experience
** Researcher — CAAR REU (QuICS)
:PROPERTIES:
:ID: 809dd6f7-7700-43ae-ac87-ae2ec79ab4ef
:ROLE: Researcher
:COMPANY: CAAR REU (QuICS)
:DATES: Jun 2025 Aug 2025
:END:
- Created families of fault-tolerant CSS quantum error-correcting codes for qudits.
- Proved transversal Clifford and T gate support using finite field and QEC theory.
- Built parallel Python tooling (Galois, NumPy, Magma, SageMath) to test self-orthogonality and distance.
** Undergraduate Researcher — Bright Beams Collective (IREAP)
:PROPERTIES:
:ID: 4ee96812-4a42-4fce-ab41-223dc3237ed1
:ROLE: Undergraduate Researcher
:COMPANY: Bright Beams Collective (IREAP)
:DATES: Sep 2023 Dec 2024
:END:
- Designed machine learning and gradient optimizers for particle accelerator beamline tuning.
- Ran MAD-X and Elegant simulations to evaluate lattice stability and beam quality.
- Produced Fusion 360 and Ansys visualizations for educational and technical presentations.
** Software Engineering Intern — JODO PAY
:PROPERTIES:
:ID: 9ca345ca-c318-4d70-aa4d-8542bc322589
:ROLE: Software Engineering Intern
:COMPANY: JODO PAY
:DATES: Jun 2022 Jul 2022
:END:
- Automated invoice generation and delivery via Google Workspace APIs.
- Reduced manual processing by approximately 40 staff hours each week.
- Hardened error handling and template management with TypeScript and Apps Script.
* Projects
** Quantum State Tomography via QML
:PROPERTIES:
:ID: 28f564fa-8ac8-4720-bf5c-cf999186cf6d
:NAME: Quantum State Tomography via QML
:TIMELINE: Sep 2024 Jul 2025
:END:
- Co-developed variational circuit tomography with custom losses and embeddings.
- Launched 2,000+ experiments across multi-GPU clusters via bespoke orchestration tools.
- Co-author on "Quantum state reconstruction with variational quantum circuit" (arXiv:2507.01246).
** MIT iQuHack — QuEra Challenge
:PROPERTIES:
:ID: 25c4d9b7-ea24-4af7-8cac-f1855743abc6
:NAME: MIT iQuHack — QuEra Challenge
:TIMELINE: Feb 2025
:END:
- Built a compilation pipeline translating QAOA and error-correcting circuits into neutral atom instructions.
- Optimized pulse schedules using Qiskit, Cirq, Bloqade, PyTorch, and TensorFlow Quantum.
- Team earned an Honorable Mention from QuEra.
** Club Administration Automation
:PROPERTIES:
:ID: e00b83aa-277b-4379-96aa-989754fefbcb
:NAME: Club Administration Automation
:TIMELINE: Nov 2024 Feb 2025
:END:
- Automated Discord announcements, email campaigns, Instagram posts, and room reservations.
- Integrated Google APIs, Discord.py, Selenium, and OAuth2 for end-to-end workflows.
- Adopted by multiple university clubs to reduce administrative effort.
** Quantum ML Research Collection
:PROPERTIES:
:ID: 5a0897f1-4b2c-4dd4-a68e-8a324822f425
:NAME: Quantum ML Research Collection
:TIMELINE: Aug 2023 Dec 2024
:END:
- Crafted quantum image processing pipelines with parameterized kernels inside CNNs.
- Designed a hybrid transitional optimizer that mitigates barren plateaus in QAOA.
- Presented findings at the 2024 First Year Innovation & Research Experience Summit.
** Housing Market Analysis
:PROPERTIES:
:ID: 25053703-72e2-492d-bf8b-4a5953b6160e
:NAME: Housing Market Analysis
:TIMELINE: Jun 2024 Jul 2024
:END:
- Built feedforward neural networks to predict housing prices from public datasets.
- Applied PCA and statistical analysis to surface high-signal features.
- Combined web-scraped listings with census data to improve model robustness.
** Indie Game Development
:PROPERTIES:
:ID: bdf83287-24aa-4f55-9a07-e11d6e08e319
:NAME: Indie Game Development
:TIMELINE: 2020 2023
:END:
- Shipped two action platformers with custom soft-body simulation via Unity/Unreal.
- 2nd place, 2021 Mindbox National Design Championship (Game Design).
- National finalist, 2020 Mindbox Design Championship (Game Development).
- Authored a procedural map generation toolkit for arbitrary tilemaps.
* Education
** University of Maryland — College Park
:PROPERTIES:
:ID: 86d31d81-d7e2-4035-9441-54badb1724a7
:SCHOOL: University of Maryland — College Park
:GPA: 3.974
:GRADUATION: May 2027
:END:
- degree :: B.S. Computer Science (Honors)
- degree :: B.S. Physics (Honors)
- honor :: Angelo Bardasis Scholarship — Physics
- honor :: John D. Gannon Scholarship — Computer Science
- honor :: Dean's List — Every Semester
- course :: Graduate Quantum Computing (CMSC657)
- course :: Differentiable Programming for Agentic AI (CMSC498Z)
- course :: Natural Language Processing (CMSC470)
- course :: Data Science (CMSC320)
- course :: Design & Analysis of Algorithms (CMSC451)
- course :: Honors Advanced Modern Physics (PHYS400)
- course :: Quantum Mechanics II (PHYS402)
* Organizations
** Industry Chair — Quantum Coalition
:PROPERTIES:
:ID: 9ed6f6b0-5389-485f-aa00-e6c934737e3d
:ROLE: Industry Chair
:ORG: Quantum Coalition
:DATES: Jan 2024 Present
:END:
- Co-organized the QRISE research competition with 200+ global participants.
- Partnered with the UN and ITU to deliver the QC-FLIQ hackathon (500+ attendees).
** President — Undergraduate Quantum Association
:PROPERTIES:
:ID: c458048e-95be-4726-9345-b4af7650ba4d
:ROLE: President
:ORG: Undergraduate Quantum Association
:DATES: Jan 2025 Present
:END:
- Led programming, partnerships, and outreach after four years as an officer.
- Hosted the Quantum Leap Career Nexus with 240+ attendees across IBM, Microsoft, Amazon Braket, IonQ, and more.
** Co-President — ACM@UMD
:PROPERTIES:
:ID: 145dbb0c-cf88-46e0-bc3e-052120e83978
:ROLE: Co-President
:ORG: ACM@UMD
:DATES: Sep 2023 Present
:END:
- Restarted the official student chapter and launched a new web presence.
- Grew membership to 145+ students with workshops on shell scripting, AI, and quantum computing.
* Publications
** Quantum state reconstruction with variational quantum circuit
:PROPERTIES:
:ID: 0f86c17a-6165-4b78-9610-5d6cb3da2977
:TITLE: Quantum state reconstruction with variational quantum circuit
:STATUS: Preprint — arXiv:2507.01246
:END:
- Introduces a quantum machine learning approach to tomography for high-dimensional states.
- Benchmarks loss landscapes, embedding strategies, and optimizer behavior across noise models.
- Highlights scalability results enabled by custom experiment orchestration.
** A Very Quick Guide to Special Relativity
:PROPERTIES:
:ID: e7c3273b-0c2b-43d4-94fc-fca989893799
:TITLE: A Very Quick Guide to Special Relativity
:STATUS: Published — 2021
:END:
- Wrote and published an accessible primer covering time dilation through mass-energy equivalence.
- Focused on first-principles explanations for students exploring modern physics.
* Skills
** Languages
- Python
- C
- C++
- JavaScript/TypeScript
- Rust (learning)
** Quantum
- Qiskit
- Cirq
- PennyLane
- Q#
- Bloqade
** ML
- PyTorch
- TensorFlow Quantum
- NumPy
- SciPy
- scikit-learn
- MPI
- Numba
** Simulation
- MAD-X
- Elegant
- Magma
- SageMath
- Fusion 360
- Ansys Workbench
** Tools
- Git
- Docker
- Google Cloud APIs
- Selenium
- Discord.py
- REST APIs

@ -0,0 +1,212 @@
#!/usr/bin/env node
// =============================================================================
// Module contract (praxis: Contract-First Modules · The Docstring Is the Contract)
//
// provides — parse the canonical résumé (resume.org, RESUME_SCHEMA: 1) into a
// deterministic JSON mirror (resume.json). One concern: org -> json.
// requires — Node >=18 (readFileSync, writeFileSync, JSON). No dependencies:
// the schema is small and self-owned, so a maintained org parser
// (orga / uniorg) would be more liability than a ~120-line reader.
// tests must show —
// * every `**` item heading with an :ID: becomes one object carrying its id;
// * drawer keys map to lowercased fields; tagged bullets (`- k :: v`) route
// into named arrays; plain bullets become `bullets`;
// * skills categories and the profile drawer + bio prose are captured;
// * output is byte-stable (sorted-nothing, fixed key order, 2-space, \n) so
// the CI canary (regenerate + git diff) only trips on real drift.
//
// Flow is ONE-WAY: resume.org -> resume.json. Never hand-edit resume.json.
// Usage: node scripts/org-to-json.mjs [resume.org] [resume.json]
// With --check it regenerates in memory and exits non-zero if the file on disk
// differs (the drift canary), without writing.
// =============================================================================
import { readFileSync, writeFileSync } from 'node:fs';
const GENERATED_NOTE =
'GENERATED FILE — do not edit. Source of truth: resume.org. ' +
'Regenerate: node scripts/org-to-json.mjs';
// Section registry — the fixed schema the parser understands.
const SECTIONS = {
profile: { kind: 'profile' },
experience: { kind: 'items', fields: ['role', 'company', 'dates'] },
projects: { kind: 'items', fields: ['name', 'timeline'] },
education: {
kind: 'items',
fields: ['school', 'gpa', 'graduation'],
tagged: { degree: 'degrees', honor: 'honors', course: 'coursework' },
},
organizations: { kind: 'items', fields: ['role', 'org', 'dates'] },
publications: { kind: 'items', fields: ['title', 'status'] },
skills: { kind: 'skills' },
};
const slug = (s) => s.trim().toLowerCase();
const isHeading = (l) => /^\*+\s/.test(l);
const headingLevel = (l) => (l.match(/^(\*+)\s/) || [, ''])[1].length;
const headingText = (l) => l.replace(/^\*+\s+/, '').trim();
// Read a :PROPERTIES: ... :END: drawer starting at `start`; return {props, next}.
function readDrawer(lines, start) {
const props = {};
let i = start + 1;
for (; i < lines.length; i++) {
const t = lines[i].trim();
if (t === ':END:') return { props, next: i + 1 };
const m = t.match(/^:([A-Za-z0-9_]+):\s*(.*)$/);
if (m) props[m[1].toLowerCase()] = m[2].trim();
}
throw new Error(`Unterminated :PROPERTIES: drawer at line ${start + 1}`);
}
// Build one item object from its heading, drawer props, and bullet lines.
function makeItem(cfg, props, bullets) {
const item = {};
if (props.id) item.id = props.id;
for (const f of cfg.fields) if (props[f] != null) item[f] = props[f];
const tagged = cfg.tagged || {};
for (const key of Object.values(tagged)) item[key] = [];
const plain = [];
for (const raw of bullets) {
const m = raw.match(/^([A-Za-z0-9_]+)\s*::\s*(.*)$/);
if (m && tagged[m[1].toLowerCase()]) {
item[tagged[m[1].toLowerCase()]].push(m[2].trim());
} else {
plain.push(raw);
}
}
if (!cfg.tagged) item.bullets = plain;
return item;
}
function parse(text) {
const lines = text.split(/\r?\n/);
const out = {
profile: {},
experience: [],
projects: [],
education: [],
organizations: [],
publications: [],
skills: {},
};
const bioLines = [];
let section = null; // {key, cfg}
let itemProps = null; // drawer of the open item
let itemBullets = null; // bullets of the open item
let skillCat = null; // {key, list}
const flushItem = () => {
if (section && section.cfg.kind === 'items' && itemProps !== null) {
out[section.key].push(makeItem(section.cfg, itemProps, itemBullets));
}
itemProps = null;
itemBullets = null;
};
const flushSkill = () => {
if (skillCat) out.skills[skillCat.key] = skillCat.list;
skillCat = null;
};
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
const t = line.trim();
if (t.startsWith('#') || t === '') continue; // comments, keywords, blanks
if (t === ':PROPERTIES:') {
const { props, next } = readDrawer(lines, i);
i = next - 1;
if (section && section.cfg.kind === 'items' && itemProps !== null) {
Object.assign(itemProps, props);
} else if (section && section.key === 'profile') {
Object.assign(out.profile, props);
}
// file-level drawer (no section yet) is metadata — ignored.
continue;
}
if (isHeading(line)) {
const level = headingLevel(line);
const label = headingText(line);
if (level === 1) {
flushItem();
flushSkill();
const key = slug(label);
section = SECTIONS[key] ? { key, cfg: SECTIONS[key] } : null;
if (!section) process.stderr.write(`warn: unknown section "${label}"\n`);
} else if (level === 2 && section) {
if (section.cfg.kind === 'items') {
flushItem();
itemProps = {};
itemBullets = [];
} else if (section.cfg.kind === 'skills') {
flushSkill();
skillCat = { key: slug(label), list: [] };
}
}
continue;
}
if (t.startsWith('- ')) {
const val = t.slice(2).trim();
if (section && section.cfg.kind === 'items' && itemBullets) itemBullets.push(val);
else if (section && section.cfg.kind === 'skills' && skillCat) skillCat.list.push(val);
continue;
}
// free prose — only meaningful inside Profile (the bio).
if (section && section.key === 'profile') bioLines.push(t);
}
flushItem();
flushSkill();
if (bioLines.length) out.profile.bio = bioLines.join(' ');
return out;
}
// Stable serialization: fixed top-level key order, 2-space indent, trailing \n.
function serialize(data) {
const ordered = {
$generated: GENERATED_NOTE,
profile: data.profile,
experience: data.experience,
projects: data.projects,
education: data.education,
organizations: data.organizations,
publications: data.publications,
skills: data.skills,
};
return JSON.stringify(ordered, null, 2) + '\n';
}
function main() {
const args = process.argv.slice(2).filter((a) => a !== '--check');
const check = process.argv.includes('--check');
const src = args[0] || 'resume.org';
const dst = args[1] || 'resume.json';
const json = serialize(parse(readFileSync(src, 'utf8')));
if (check) {
let current = '';
try {
current = readFileSync(dst, 'utf8');
} catch {
/* missing file counts as drift */
}
if (current !== json) {
process.stderr.write(
`DRIFT: ${dst} is out of sync with ${src}. Run: node scripts/org-to-json.mjs\n`,
);
process.exit(1);
}
process.stdout.write(`ok: ${dst} matches ${src}\n`);
return;
}
writeFileSync(dst, json);
process.stdout.write(`wrote ${dst} from ${src}\n`);
}
main();
Loading…
Cancel
Save