Build it
The tax brand's folder, one file at a time. Your code first, then its words, its rules table and its Pool, then ten Services, with check after each one and the plan each file needs.
tax's wordsreturn is a jobtaxpayer is a subjectreview is a taskpreparer is a member
The brand is a folder. Write its files in this order and run check after each. It counts lines of code only, and prints under each file the services.dev plan its keys need, with the line that sets it.
| File | What it adds | Plan |
|---|---|---|
lib/tax.ts | your code: the calendar, each jurisdiction's rules, the request list, the schedules, the tentative tax, the estimates, the notice match, and a simulated e-file system a live brand swaps for its transmitter | none |
brand.ts | the words, four credentials the brand holds, and the calendar: Brand() | Launch, for the domain |
rules.ts | who may perform each act, per Service, each row illustrative with its position: the rules table | Free: the floor |
pools/preparers.ts | three credentialed roles, a door of its own, protections and standby: the Pool | Team |
| Four small Services | the estimate, the question, the notice response and the amendment, which the plan orders | Launch |
services/carryforward-watch.ts | the steward a return names, before the return that imports it | Launch |
services/annual-return.ts | the return: the §7216 consent, kept facts, the organizer, a signature for the brand's firm, a filing per jurisdiction, five clocks and a guarantee: Annual return | Team |
services/information-returns.ts | the year's 1099s, under the brand's own codes: Information returns | Launch |
services/tax-plan.ts, services/transcript.ts | the year that orders the rest, and lender records, the table's last name | Team, and Free |
services/year-end-close.ts | the books, closed by AI, with an accountant's approval sold on top, from a Pool another operator runs | Launch |
$ cat lib/tax.ts
export type ByJurisdiction = Record<string, number>
export const irs: Calendar = { zone: 'America/New_York', weekends: ['saturday', 'sunday'], closed: holidays, closes: '23:59', rings_at: '09:00', roll: 'next open day' }
export function holidays(year: number): string[] {
export const SCENARIOS: Readonly<Record<string, Readonly<Record<string, string>>>> = {
export const formOf = (entity: string, at: string) => FORMS[entity]?.[at] ?? 'the state return'
export const authorization = (job: AnyView) => (job.input.entity === 'partnership' ? 'Form 8879-PE' : 'Form 8879-CORP')
$ cat brand.ts
import { Brand } from 'services.dev'
import { irs } from './lib/tax.ts'
// A tax brand shaped like the .tax family, proving Time.
$ cat rules.ts
import { Rules } from 'services.dev'
// Rows per Service, frozen and versioned, each illustrative: a brand's counsel writes its real table, and every row
// records what the brand does and why. A paid preparer holds a PTIN; on a California leg, a CTEC registrant, a CPA, an
$ cat pools/preparers.ts
import { Pool } from 'services.dev'
import { keptUntil } from '../lib/tax.ts'
// One Pool for every tax Service, on gigs.tax. The verifier checks each credential and renews the PTIN by 31 December; a
With no Service yet, check has nothing to sell:
npx services.dev check # after pools/preparers.tsNo Services here.
next npx services.dev initThe estimate is AI and code, with the officer deciding. Now check reads the whole folder:
$ cat services/estimate.ts
import { Service } from 'services.dev'
import { estimateDue, estimateFor, underpaymentCost } from '../lib/tax.ts'
// A quarter's estimated payments, the owner deciding. The quarter is its period on the taxpayer, so a second estimate for
$ npx services.dev check # after services/estimate.ts
plan Launch (services.dev) · Brand.domain at :9
plan Team (services.dev) · Pool.door at :11, gigs.tax, a door your account operates · Pool.firms at :29 · Pool.affinity at :30 · Pool.standby at :32
services/estimate.ts · 17 lines · $79 per job, within 48 hours, charged on delivery.
The question names a rules row, so check holds the brand at rule_unread until the table's other Services are written:
$ cat services/question.ts
import { Service } from 'services.dev'
import { preparers } from '../pools/preparers.ts'
import rules from '../rules.ts'
$ npx services.dev check # after services/question.ts
services/question.ts · 10 lines · $49 per job, within 48 hours, charged on delivery.
plan Launch (services.dev) · subject at :14 · roles.signer.pool at :15
✗ The rules table binds a name nothing reads: a key that names no Service file, or a row no step performs that is neither an advice class nor refused. Rename it to what it means, or take it out. rules.services has a key 'annual-return', and no Service file is services/annual-return.ts. rules.services has a key 'amended-return', and no Service file is services/amended-return.ts. rules.services has a key 'notice-response', and no Service file is services/notice-response.ts. rules.services has a key 'information-returns', and no Service file is services/information-returns.ts. rules.services has a key 'transcript', and no Service file is services/transcript.ts.
The notice response, then the amended return:
$ cat services/notice-response.ts
import { Service } from 'services.dev'
import { classify, matchPayments } from '../lib/tax.ts'
import { preparers } from '../pools/preparers.ts'
import rules from '../rules.ts'
$ npx services.dev check # after services/notice-response.ts
services/notice-response.ts · 19 lines · $299 per job, or $99 if you answer it yourself, or 25% of a penalty abated, $99 at least, within 48 hours, charged on send's receipt.
self The owner may answer it themselves, in their own name, for $99.
✗ The rules table binds a name nothing reads: a key that names no Service file, or a row no step performs that is neither an advice class nor refused. Rename it to what it means, or take it out. rules.services has a key 'annual-return', and no Service file is services/annual-return.ts. rules.services has a key 'amended-return', and no Service file is services/amended-return.ts. rules.services has a key 'information-returns', and no Service file is services/information-returns.ts. rules.services has a key 'transcript', and no Service file is services/transcript.ts.
$ cat services/amended-return.ts
import { Service } from 'services.dev'
import { authorization, carryforwardList, efile, schedules } from '../lib/tax.ts'
import { preparers } from '../pools/preparers.ts'
import rules from '../rules.ts'
$ npx services.dev check # after services/amended-return.ts
services/amended-return.ts · 22 lines · $900 per job, within 30 days, charged when file or aar is accepted.
plan Launch (services.dev) · subject at :20 · roles.preparer.pool at :21
✗ The rules table binds a name nothing reads: a key that names no Service file, or a row no step performs that is neither an advice class nor refused. Rename it to what it means, or take it out. rules.services has a key 'annual-return', and no Service file is services/annual-return.ts. rules.services has a key 'information-returns', and no Service file is services/information-returns.ts. rules.services has a key 'transcript', and no Service file is services/transcript.ts.
$ cat services/carryforward-watch.ts
import { Service } from 'services.dev'
import { earliestExpiry } from '../lib/tax.ts'
// The steward a taxpayer keeps once no plan runs: it answers for the dates a return leaves on the subject. The brand
$ npx services.dev check # after services/carryforward-watch.ts
services/carryforward-watch.ts · 8 lines · $9 per year, charged at the start of each year.
clocks expiring · a date your code decides · the brand · on the taxpayer
plan Launch (services.dev) · subject at :11 · clocks.lives_on: 'subject' at :13 · price.every at :14
$ cat services/annual-return.ts
import { Service } from 'services.dev'
import { assessmentCloses, authorization, carryforwardList, claimsRefund, earliestExpiry, efile, extendedDue, extension, fileDue, lateCost, lateFiling, payDue, reask, refundCloses, requestList, schedules, tentative } from '../lib/tax.ts'
import { preparers } from '../pools/preparers.ts'
import rules from '../rules.ts'
$ npx services.dev check # after services/annual-return.ts
services/annual-return.ts · 45 lines · $1,800 per job, filed 5 days before its deadline, 20% off if late, or we pay the penalty and its interest, up to $5,000, after we ask the IRS to take it off, charged when file is accepted.
clocks file · a date your code decides, one for each jurisdiction · the member of record · moves on extend to a date your code decides · about 5% of the unpaid tax a month late, or $245 an owner · guarantee: penalties and their interest, up to $5,000, after notice-response, never for held time, from your line
pay · a date your code decides · the buyer · hard: nothing moves it · about 0.5% of the unpaid tax a month late
$ cat services/information-returns.ts
import { Service } from 'services.dev'
import { payees } from '../lib/tax.ts'
import rules from '../rules.ts'
$ npx services.dev check # after services/information-returns.ts
services/information-returns.ts · 17 lines · $15 per payee, charged when file is accepted.
bounds open match, under the brand's tin_matching · open file, under the brand's iris
✗ The rules table binds a name nothing reads: a key that names no Service file, or a row no step performs that is neither an advice class nor refused. Rename it to what it means, or take it out. rules.services has a key 'transcript', and no Service file is services/transcript.ts.
The Tax Plan and the transcript each show their file. The transcript reads the table's last name, and the brand is ready to sell:
$ npx services.dev check # after services/tax-plan.ts
services/tax-plan.ts · 18 lines · $2,400 per year, charged at the start of each year, 1 annual-return, 25 information-returns payees, 4 estimate, 12 question and 2 notice-response included each year.
plan Team (services.dev) · on.event at :29, past the Tax Plan's allowance: fact.restated mints an amended return
✗ The rules table binds a name nothing reads: a key that names no Service file, or a row no step performs that is neither an advice class nor refused. Rename it to what it means, or take it out. rules.services has a key 'transcript', and no Service file is services/transcript.ts.
$ npx services.dev check # after services/transcript.ts
services/transcript.ts · 18 lines · roadmap · $12 per job, within 48 hours, charged on order's receipt, or at disclose for a return the brand filed.
✓ ready to sell · 9 Services · AI delivers 2 alone · each keeps at least 50% of every job$ cat services/year-end-close.ts
import { Service } from 'services.dev'
// The year's books, closed before the return reads them. The AI reconciles each account to its statement and proposes
// the adjusting entries, an adversarial tie-out checks them, and the officer decides which to post. For $900 instead of
$ npx services.dev check # after services/year-end-close.ts
ledger +$900.00 · AI $1.26 (example) · preparer $150.00 · signer $105.00 · you $643.74 · 4 jurisdictions
services/year-end-close.ts · 15 lines · $300 per job, or $900 with an accountant's approval, within 48 hours, charged on delivery.
roles accountant · from gigs.accountants/accountants, a Pool another operator runs · $250 an approval · placement $20.00 a filled review
Every branch runs what these files can do, and its plans read the folder back as one.