Excel Intelligence & Controls
A method and toolset for reverse-engineering formula-driven business Excel workbooks as undocumented legacy code: profile the workbook and its structure → convert it to structured Markdown → extract the field ontology → reconstruct formula chains and cross-workbook lineage → verify the interpretation row by row against the full dataset → then produce annotated results, a business analysis report, and a web dashboard.
Current authority and public boundary: the Browser Analyzer now performs structure profiling, formula-family grouping, dependency evidence mapping, Excel-error preservation, and review-queue export in page memory without a backend or model API key. The stable local Agent authority is 1.34.0 with five Skills; it uses Python, SQLite, an Agent host, and human review. This page preserves the earlier consolidated method PRD as provenance, so its six-step command details are historical rather than the current 1.34 interface. The public evidence remains synthetic, with no production adoption claimed.
This page presents PRD/excel-ai-analyst-PRD-v1.0.md online.
It consolidates the original, v1, v2, and v3 materials and source under prePRD/,
and reflects the delivered E1 logic layer and management-reporting domain package (M) counts.
The second volume, “From One Analysis to an Ontology Asset” (ontology platform · two gates · team spaces · knowledge flywheel), is in
PRD/excel-ai-analyst-PRD-v2.0.md and is not yet represented online.
01 · RequirementsContext and problem definition
What enterprise Excel really is
In many companies, Excel does more than record data. It is the business system actually running the process. A mature payroll workbook, cost model, or inventory ledger often looks like this:
| Characteristic | Typical scale |
|---|---|
| Header depth | 2–4 rows (title + grouped headers + field names + units) |
| Column count | 40–120 columns |
| Formula nesting | 4–7 layers (inputs → intermediate values → subtotals → totals → deductions → final result) |
| Cross-sheet references | 3–10 sheets pulling data from one another |
| Years in use | 3–10 years across multiple maintainers |
| Documentation | None |
It carries real money: payroll, cost reporting, commissions, and budgets. It runs every month. When it fails, someone may be underpaid or the company may overspend. Yet it has no version control, tests, documentation, or change history. Its original author may have left, and the current maintainer may know only that “these columns must not be touched.”
Four common dilemmas
Taking over a workbook nobody can explain
The problem is not one unreadable formula. It is not knowing the workbook's overall logic: which fields are inputs, which are results, and what a single change will affect downstream.
Wanting AI automation without trusting it
Technically, yes. The real question is: how do you prove that AI learned the business logic? Misread one coefficient and it can calmly return a payroll file that looks normal while underpaying every person by 200. The error will not announce itself; it will be delivered.
Suspecting an error without knowing where to look
Sampling is ineffective because the error may exist in only a few rows. Manual full-dataset review is unrealistic: 3,000 rows across seven formulas create 21,000 validation points.
Running analysis on an unstable foundation
The answer depends entirely on understanding the formula chain: does the social-insurance base increase too? How is the performance base calculated? If any link is misunderstood, the scenario result is wrong.
Why general AI fails when reading Excel directly
Sending an xlsx file directly to a general-purpose model creates five failure modes. Together, they explain why this product exists:
| Problem | Consequence |
|---|---|
① Multi-row headers are misreadread_excel treats the first row as the header by default |
A three-row header becomes Unnamed: 0 and similar fields, stripping the workbook of its meaning |
| ② Formulas are invisible The reader sees cached results, not formulas |
AI sees a column of numbers with no way to know whether it came from A+B-C or A*B/C |
| ③ Merged cells misalign column names | Only the top-left cell of a merged range contains a value, so multi-row header assembly can attach labels to the wrong columns |
| ④ Plausible hallucination | AI assigns a common-sense formula to “Gross Pay.” It is often reasonable, but may not be the formula this workbook uses; one missing term can invalidate every row |
| ⑤ No verification stage | The most serious failure. The user receives a confident report with no way to know which claims are true |
02 · RequirementsGoals and boundaries
✓ Goals
- G1 Reconstruct the complete calculation logic without contacting the original author
- G2 Turn “understood” into measurable criteria: pass rate plus exception count
- G3 Explain the workbook and find errors in the workbook itself
- G4 Preserve a one-time interpretation as a reusable asset in
spec.json - G5 Run analysis and What-If scenarios only on a verified interpretation
- G6 Work across workbook types through three orthogonal dimensions: archetype × structure × rule set
- G7 Produce shareable, presentation-ready results in a single-file offline dashboard
✗ Non-goals
- N1 Calculations requiring cross-period state, such as cumulative personal-income-tax withholding. Being unable to calculate is expected; state which inputs are missing rather than forcing a result or widening tolerance
- N2 Hidden rules outside the workbook, such as commission tiers or social-insurance limits. The system can locate evidence that a rule exists, but the only correct next action is to ask a person
- N3 Tables embedded in images, scans, or PDFs, which require OCR first
- N4 Business correctness of source values, such as whether a person's base salary should be 12,000
- N5 Real-time or large-scale data pipelines: up to 100,000 rows, while million-row workloads belong in a database
- N6/N7 Simple reading, writing, or cleaning tasks, or workflows whose target output is Word or PowerPoint
- N8 Writing changes back to the source workbook—the user's original file is never modified
Success measures
Five workbook issue types the method can find
These checks can find errors in the workbook itself, not only explain how its formulas work.
| Issue type | Typical pattern | Can a person find it? | Detection path |
|---|---|---|---|
| ① Formula manually overwritten | A formula is replaced by a fixed value to make the total balance; only a few rows differ, often by round values such as 120, 500, or 1,000 | Nearly impossible | checks row recalculation plus formula-breakpoint detection |
| ② Formula range omits a column | =SUM(C2:G2) should be =SUM(C2:H2); a new month was added but the total formula did not expand |
Difficult | identity horizontal reconciliation |
| ③ Cross-period discontinuity | Inventory closes at 100 last month but opens at 137 this month | Requires SKU-by-SKU, month-by-month review | continuity |
| ④ Orphan foreign-key reference | A department, item, or customer in the business table does not exist in master data | Requires a full-table comparison | foreign_key |
| ⑤ Unit or definition inconsistency | Some people accrue commission on sales while others use cash collected; the same item mixes units such as pieces and cases | Requires recognizing a fixed-ratio or integer-multiple difference pattern | Difference-pattern interpretation |
03 · RequirementsUsers and scenarios
Business user
A finance, HR, or supply-chain specialist taking over a legacy workbook.
Concern: How does it calculate, and are the calculations correct?
Mode: Conversational—drop the workbook into Cowork or Claude and ask questions.
Implementer
A digitalization or data-analysis practitioner turning a monthly process into a repeatable workflow.
Concern: Can it run automatically each month and connect to CI?
Mode: Command line plus spec.json.
Platform developer
A platform engineer integrating the methodology into an existing data platform.
Concern: Required behavior for every subcommand.
Mode: Implement from the SKILL.md specification.
Key user stories
| ID | As a | I want to | So that I can |
|---|---|---|---|
| US-1 | Business user | Give AI a legacy workbook and have it explain where every column comes from | Take ownership and make changes with confidence |
| US-2 | Business user | Know whether AI's interpretation is actually correct | Avoid being misled by a confident but wrong report |
| US-3 | Finance specialist | Find the few rows causing this month's labor-cost mismatch | Locate and assign the correction |
| US-4 | Implementer | Rerun the full workflow each month by changing only a path | Turn two days of work by three people into one command |
| US-5 | Implementer | Use exit codes in CI or a scheduled job | Raise an alert as soon as a workbook has an issue |
| US-6 | Manager | See who is affected by a change and how a 10% pay increase changes total cost | Make decisions |
| US-7 | Any user | Send results to a colleague with no special tools | Share a single offline web file that opens with a double-click |
| US-8 | Platform developer | Receive the behavioral specification for every subcommand | Reimplement it in an environment without Python |
04 · ConceptCore metaphor: the workbook is code
The methodology is built on one metaphor. It is not rhetoric, but an operational mapping:
| Workbook element | Equivalent code concept | Resulting action |
|---|---|---|
| Column name | Variable name | Build a symbol table: the field ontology |
| Cell formula | Function body | Extract it and recalculate every row as a regression test |
Formula written in a header, such as GrossG=A+B-C | Pseudocode in a comment | Compare it with the real formula; when they differ, the real formula governs |
| Cross-sheet reference | Module dependency | Draw the call graph: data lineage |
| Check or Countif column | Unit test | A free test case—use it first |
| Total row | Assertion | The detail rows must sum to it |
| “Do not edit formula” comment | Documentation comment | Distinguishes results from inputs |
| Multi-layer formula nesting | Call stack | Understand it in layers; a flat list carries little information |
| Hidden rows or columns | Commented-out code | Inspect them, but do not treat them as active data |
Three deductions
Understanding a workbook is code archaeology
You would not understand unfamiliar code by inspecting a few variable values. You would read definitions, trace calls, and run tests. A workbook is no different.
It is understood only when it is tested
Software engineers do not accept “I understand this code” without tests. “I understand this workbook” should likewise require full-dataset recalculation.
The error may be in the workbook, not the interpretation
When a test fails, the reviewer must determine whether the interpretation is wrong or the workbook itself is calculating incorrectly.
05 · ConceptThree design principles
Principle one · Verification first
This is the foundation of the methodology. Every conclusion about a workbook must rest on an AI interpretation that has passed full-dataset regression testing. The hard rules are:
- The row-level pass rate must be 100%; 98% is not a pass
- Workbook-level checks must have zero exceptions, or every exception must have an explicit explanation
- Tolerances must never be widened to make a report look better: 0.01 for amounts and 0.0001 for ratios
- Every mismatch must be assessed individually: is the interpretation wrong, or is the workbook wrong?
The tooling enforces this discipline. A formula that scaffold cannot translate is marked TODO.
If verify detects a TODO, it refuses to run and returns exit code 2.
Verification cannot begin with an incomplete interpretation.
Principle two · Human–machine division of work
| Type | Work | Owner | Reason |
|---|---|---|---|
| Mechanical work | Read files, extract formulas, assemble headers, recalculate rows, and aggregate statistics | Script | Accurate, fast, and repeatable; AI is slower and less reliable at this work |
| Cognitive work | Interpret what a column means, what / signifies, and which business definition a coefficient follows |
AI | Business meaning is not in the file; it lives in the context behind the column names |
Steps 2 and 3 are deliberately not automated. A script can extract
=D4+E4-G4, but it cannot infer that “column G is the employee share of social insurance, capped by local base limits, and not deducted in the termination month.” The value of this step lies precisely in what cannot be automated.
Principle three · Progressive disclosure
Nine archetypes, nineteen rule types, and four structural shapes would dilute attention if loaded all at once. The documentation is therefore layered.
The output from profile tells AI which reference to read next:
SKILL.md (core document, about 650 lines)
└─ Method skeleton + when to open each reference
├─ references/patterns/xxx.md ← read only after profile identifies that archetype
├─ references/table_shapes.md ← read the relevant section when the shape is not long
├─ references/check_library.md ← consult when configuring table_checks
└─ references/spec_schema.md ← consult when writing a spec06 · MethodSix steps, plus two extensions
If a workbook is code, the standard process for understanding unfamiliar code maps directly to the product workflow:
① Identify the kind of project → Step 0 Profile archetype and structure
② Read and format the code → Step 1 Convert to structured Markdown
③ Build the symbol table → Step 2 Define the field ontology
④ Draw the call graph → Step 3 Reconstruct formulas and lineage
⑤ Run the test suite → Step 4 Verify the full dataset ★
⑥ Change or analyze only after pass → Step 5 Deliver and run scenariosprofile Scriptlong/wide/matrix/block using
column names only, not the share of numeric values; infer header_rows; assign a role to each column; and suggest check directions.
Produces 00-profile-report.md plus profile.json.
The report is a machine hypothesis, not a conclusion. If header_rows is off by one, everything downstream is invalid.tomd Scriptrange_boundaries;
skip title rows spanning the whole sheet; extract real formulas with data_only=False;
warn on types using the to_numeric success rate; and translate simple same-row formulas into draft expressions.
Translation stops on IF: no translation is safer than a wrong guess.scaffold Scriptheader_rows/keys/dimensions/fields automatically. Translatable formulas become checks;
everything else becomes TODO. This is only a draft. Do not send it directly to verify.source.field → target.field / join key / explanation.
Finish with a table mapping each perturbable input to its impact layer so What-If scenarios can follow it directly.verify Scriptchecks recalculate every row against the Excel result column;
4·2 workbook level, with nineteen general table_checks types;
4·3 cell level, with provenance and formula-breakpoint detection;
and 4·4 cross-sheet cross_checks.
Exit codes 0/1/2 connect directly to CI.graph Scriptkeys, attributes through fields,
and links through foreign_key. This reads existing definitions rather than inferring new meaning. The information already exists in the spec
and is extracted with the AST. Produces ontology.json, Mermaid, and an impact ranking.output / analyze Scriptdashboard Script07 · MethodWhy verification needs two layers
Row-level verification with checks recalculates every row using the AI interpretation
and compares it with the workbook's existing result column:
AI interpretation: gross = base + allowance + commission − deduction
↓ substitute each row
9745.14 ←→ 9865.14 (Excel value)
↓
difference −120.00 ❌This can prove that each row calculates correctly, but not whether the workbook contains duplicate employee IDs, whether the March closing inventory matches the April opening balance, whether a department exists in master data, whether a total row equals its details, or whether completion contains an impossible value such as 110%. Each affected row can look valid on its own; these issues appear only when the workbook is tested as a whole.
What workbook-level checks add
| Group | Rules | Question answered |
|---|---|---|
| Data quality | unique duplicate non_null domain range non_negative | Is the workbook clean? |
| Internal consistency | identity balance total_row | Do its internal parts reconcile? |
| Time dimension | rollforward continuity sequence | Does the data connect across periods? |
| External consistency | foreign_key | Does it reconcile with other sheets? |
A concrete proof
| Seeded issue | Row only | Workbook only | Both layers |
|---|---|---|---|
| Gross pay in row 7 is manually increased by 120 | ✅ Found | ❌ Missed | ✅ |
| An employee belongs to “Strategy,” a department absent from master data | ❌ Missed | ✅ Found | ✅ |
| SKU-B has a cross-month opening/closing gap of 37 | ❌ Missed | ✅ Found | ✅ |
| The total column in a wide table omits one month | ✅ Found | ✅ Found | ✅ |
Conclusion: both verification layers are essential. For formula-free files such as rosters, master data, and CSV exports,
checksis empty—all verification value comes from workbook-level checks.
Formula breakpoints: narrow the root cause to one cell
verify records each field's column address, row range, and formula coverage, then detects formula breakpoints:
cells that are constants while most cells in the same column contain formulas.
This is the only physical trace left by a manually overwritten formula. When that cell intersects a failed row, “this column has an issue” becomes “cell
H7has the issue.”
| Cell | Field | Formula coverage | Formula sample | Intersects failed row |
|---|---|---|---|---|
H7 | E_x (verification target: Gross Pay E) | 11/12 | =D4+E4+F4-G4 | ✅ Yes, root-cause cell |
How to read results: do not assume the interpretation is wrong
| Difference pattern | Most likely cause | Next step |
|---|---|---|
| Every row differs by a fixed amount | A missing addition or subtraction | Return to Step 3 and complete the formula chain |
| Every row differs by a fixed ratio | A different coefficient, definition, or accrual base | Return to Step 2 and confirm the definition |
| Difference is an integer multiple such as 10, 100, or 1,000 | A unit problem, such as per item versus per thousand items | Confirm the unit field |
| Only a few rows differ | A manual overwrite or error in Excel | Report this high-value finding to the user |
| Difference is a round integer such as 120 or 500 | Evidence of manual balancing | Ask who changed those rows |
08 · Methodspec.json: an executable workbook interpretation
spec.json records the AI's interpretation of a business workbook in an executable form.
It turns “I believe this is how the workbook calculates” into rules that can be tested.
| Analysis report | spec.json | |
|---|---|---|
| Form | Natural language | Machine-executable |
| Verifiability | The reader can only choose whether to believe it | Run it directly; the pass rate is a hard measure |
| Reusability | Rewrite it next month | Rerun by changing the workbook path |
| Transferability | The next person must interpret it again | The next person—or AI—can take over by reading it |
| Dispute resolution | “I think it should be...” | Run the spec and inspect the data |
It turns “how this workbook calculates” from oral tribal knowledge into an executable asset. Always deliver
spec.jsonto the user.
09 · MethodHow one method handles different workbooks
The method separates three dimensions: archetype × structure × rule set. Their combination determines how to read and verify a workbook.
Dimension one · Archetype determines what to verify
| Archetype | Defining characteristic | Core checks | Largest trap |
|---|---|---|---|
| Payroll / labor cost | One person per month per row, with layered additions and deductions to net pay | Layer-by-layer recalculation + total rows | Personal income tax has memory; / is not the same as zero |
| Financial statements / account balances | Debit and credit columns plus opening and closing balances that must reconcile | balance + rollforward | Double-counting parent and child accounts; filter to leaf nodes first |
| Inventory / stock movement | Opening + inbound − outbound = closing, with periods connecting end to start | rollforward + continuity | Cross-period discontinuity is almost always a real issue |
| Sales performance / commission | Tier rules live outside the workbook; attainment rate is central | Tier recalculation + range | The accrual base is not necessarily sales; it may be cash collected or gross profit |
| Budget execution / expense control | Budget versus actual versus variance | Horizontal identity reconciliation | A SUM range in the total column omits one column—the most frequent real issue |
| Project schedule / work hours | Planned and actual dates, comparing dates rather than amounts | range + domain | Dates cannot enter expr directly; they are treated as zero |
| Production / cost BOM | Materials must balance; cost variance separates volume and price | identity: volume variance + price variance = total variance | The consumption unit can differ by three orders of magnitude |
| Master data / roster | No formulas; verify cleanliness rather than calculation | unique + foreign_key | Primary and foreign keys need bidirectional checks; Excel may coerce codes into numbers |
Dimension two · Structure determines how to feed the data
| Shape | Characteristic | Handling |
|---|---|---|
long | One record per row; columns are fields | Easiest to handle: verify row by row with no reshaping |
wide | Months, periods, or products spread across columns | For reconciliation only, keep it wide and compare derived sums. For trends, melt it into long form.
Always reference month columns by index because Actual Jan can be contained inside Actual Jan YTD |
matrix | Both rows and columns are dimensions; intersections are measures | First look for the detail source table. If only the matrix exists, use three-way reconciliation |
block | Multiple independent table blocks separated by blank rows | Split the blocks first, then treat each as an independent sheet |
Dimension three · Nineteen workbook-level checks determine how to verify
type | Purpose | Required | Optional |
|---|---|---|---|
unique | Require a field combination to be unique | fields[] | — |
duplicate | Report every repeated combination | fields[] | — |
non_null | Require fields to be non-null | fields[] | — |
domain | Require values to be in an allowlist | field, values[] | — |
range | Require a value to fall inside a range | field | min, max |
non_negative | Require a value to be non-negative | field | tolerance |
identity | Require two expressions to be equal row by row | left, right | tolerance |
balance | Require the full-table totals of two expressions to be equal | left, right | tolerance |
total_row | Require a total row to equal the detail sum | field | tolerance |
rollforward | Require opening + inbound − outbound = closing within a row | begin,in,out,end | tolerance |
continuity | Require prior-period closing = current-period opening across rows | begin,end,order_by | group_by,tolerance |
sequence | Require periods or sequence numbers to have no step gaps | field | group_by, step |
foreign_key | Require a value to exist in another sheet | field,sheet,key | workbook,header_rows |
The management-reporting domain package (M) adds six types for multi-workbook scenarios in which dozens or hundreds of business units feed one management report.
The definitions match references/check_library.md:
type | Purpose | Required | Optional | No silent downgrade |
|---|---|---|---|---|
rollup | Require Σ children = parent along a hierarchy | hierarchy{sheet,child,parent}, value_field |
field, group_by, level_field, tolerance |
Report cycles and orphans; never drop them silently |
cross_table_balance | Require two aggregated expressions across workbooks to have equal totals | left{sheet,expr,fields}, right{…} |
group_by, tolerance |
Refuse to run if the right workbook cannot be read |
period_diff | Require current month = current YTD − prior YTD | ytd_field, order_by |
group_by, mtd_field, first_period_rule, tolerance |
When the first period has no baseline, handle and label it according to the configured rule |
temporal_fk | Require a foreign key to be valid for that period | field, period_field, dim_sheet, dim_key |
workbook, valid_from, valid_to, header_rows |
If the dimension has no effective dates, refuse to run; do not downgrade to foreign_key |
sign | Require the amount direction to match the reporting-item class | field, class_field, class_sign_map |
filter, tolerance |
Zero always passes |
version_delta | Require differences between adjacent versions to have an explanation | key_fields[], value_field, version_field |
note_field, tolerance |
With only one version, skip and explain |
Two enhancements apply to existing rules. When the new parameters are not used, old specs behave byte-for-byte the same:
| Enhancement | Applies to | Description |
|---|---|---|
values_from | domain |
Read an allowlist from another sheet. If values is also present, use the union. If neither is supplied, refuse to run; a rule without criteria cannot pretend to have passed |
filter | range / non_negative / identity / balance / sign |
A Boolean expression evaluated by the restricted evaluator; the rule applies only to matching rows |
These six types reject a misconfigured green light from the start. A misspelled column name can make a rule test zero rows and still return a clean ✅. This is the most dangerous false green: no error, no warning, and a report that looks clean. An unresolved alias therefore causes the system to refuse to run with exit code
2. This gate was later extended to the first thirteen types.
Three distinctions that are easy to confuse
uniquevsduplicate: the former reports the earlier row when a value appears a second time and suits a hard constraint; the latter reports every combination appearing more than once and suits “possible duplicate—please review”checksvsidentity: the former compares the AI interpretation with an Excel result column and verifies the interpretation; the latter compares two places in the workbook that should agree and verifies the dataidentityvsbalance: the former requires equality row by row; the latter requires equality of full-table totals, even if individual rows differ—the correct expression of an accounting identity
Four questions for an unfamiliar workbook
① What does one row represent?
Define the key. One person per month? One item per warehouse per month? One line per order? If you cannot answer, the workbook is not yet understood; return to the Markdown.
② Which columns are entered, and which are calculated?
Separate the input layer from the result layer. Feeding a result column back as an input is a common error.
③ What does this workbook reconcile with?
Define cross-sheet lineage. There is always an upstream source and a downstream consumer.
④ How did the original author check it?
Look for check columns, total rows, color annotations, and comments. This is the fastest shortcut: every assertion the author left behind is a free test case.
10 · Program structureDirectories and module layers
Skill package directory
excel-ai-analyst/
├── SKILL.md Core methodology for AI, about 650 lines
├── README.md Two-minute quick start
├── docs/index.html Complete single-file offline documentation
├── scripts/excel_ai.py One-file tool with 18 subcommands, about 7,500 lines
├── references/ Progressive-disclosure reference layer
│ ├── patterns/00-index.md Nine-archetype index + four universal questions
│ ├── patterns/{payroll,finance,inventory,sales,budget,
│ │ project,production,roster,mreport}.md
│ ├── table_shapes.md Long / wide / matrix / block handling
│ ├── check_library.md Full semantics for 19 workbook-level checks
│ ├── spec_schema.md Complete spec.json field reference
│ ├── ontology_template.md Field-ontology template
│ └── lineage_template.md Formula-chain and lineage template
└── examples/
├── run_demo.sh Run the full workflow and dashboard in one command
├── make_demo_workbook.py Four-archetype demo generator with one seeded issue per sheet
├── spec_{payroll,inventory,budget}.json
└── payroll_case.md Complete walkthrough case
Internal layers of excel_ai.py
The single file has four bottom-up layers. Eighteen cmd_* entry points are dispatched through argparse subcommands:
┌─ Command layer ─────────────────────────────────────────────────────┐
│ main() → 18 argparse subcommands │
│ Core six profile / tomd / scaffold / verify / output / analyze │
│ Extensions graph / dashboard / blame / sensitivity / merge │
│ M package links / mask / reconcile / batch / restate / questions│
│ Ontology context (Step -1: load published ontology only) │
├─ Domain layer ──────────────────────────────────────────────────────┤
│ profile_sheet / suggest_checks Archetype, shape, column roles│
│ sheet_to_md / translate_formula Markdown, formula translation │
│ run_table_checks Nineteen-rule library │
│ build_provenance / find_formula_holes Cell lineage and breakpoints │
│ build_ontology / ontology_mermaid T-Box + attribute DAG │
│ plan_propagation What-If DAG propagation │
├─ Infrastructure layer ──────────────────────────────────────────────┤
│ safe_eval(AST allowlist) / num(conversion) / resolve(column refs) │
│ load_rows / expr_deps(AST dependency extraction) │
├─ Excel adapter layer ───────────────────────────────────────────────┤
│ formula_map(data_only=False) / merged_ranges / expand_merges │
│ join_headers / guess_header_rows / detect_data_start / detect_shape │
│ detect_blocks / is_title_row / is_total_row / cell_type │
└─────────────────────────────────────────────────────────────────────┘Key reuse points: safe_eval is shared by derived, checks,
table_checks, analysis.rules, and what_if.
The same AST traversal in expr_deps serves both DAG construction and What-If propagation.
Key algorithm details
| Algorithm | Key detail |
|---|---|
header_rows inference | Use the median count of numeric columns across non-empty rows to resist total and sparse rows; the first row reaching 60% of that median starts the data body; all-text sheets return 1 |
| Shape detection | Use column names only, not the share of numeric values; a normal long table may still have mostly numeric columns |
| Merged-cell expansion | Use range_boundaries, fill the full merged range with the top-left value, then join multi-row column names |
| Formula translation | Use two-stage placeholder replacement: first expand to \x01column-index\x02, then restore in one pass; otherwise an expanded C2 could be re-matched as a multi-row reference |
| Safe evaluation | ast.parse plus an allowlist traversal, not blacklist filtering; any node outside the allowlist throws an error |
| Formula-breakpoint detection | Measure formula coverage by column; if coverage meets the threshold, 0.6 by default, isolated constants are breakpoints; intersection with failed rows identifies the root cause |
| DAG construction | Use ast to collect Name nodes from expr, subtract allowed function names, and create dependency edges |
| What-If propagation | Starting at each set input, recalculate in derived declaration order, which is topological order; select affected checks as targets automatically; exclude and report unverifiable paths |
11 · Program structureData flow
Source Excel (.xlsx)
│
┌─────┴──────┐
▼ ▼
profile tomd
│ │
profile.json 01_raw_md/*.md ──────► [AI cognitive work]
│ │ Step 2 Field ontology
└──►scaffold─┘ Step 3 Formula chain and lineage
│ │
spec.draft.json ───[AI completes]────► spec.json ★ core asset
│
┌──────────────────────┼──────────────────┐
▼ ▼ ▼
verify output analyze
│ │ │
┌─────────────────┼──────────┐ AI-results.xlsx analysis-report.md
▼ ▼ ▼ whatif.json
verification-report.md verify_result.json │
mismatches.csv detail.csv │ │
table_check_issues.csv │ │
▼ │
graph ──► ontology.json ───┐ │
ontology.mmd │ │
ontology-report.md│ │
▼ ▼
dashboard
│
dashboard.html (single file)Artifact directory convention
00_profile/ Step 0 Profile report + profile.json
01_raw_md/ Step 1 Structured Markdown + index
02_ontology/ Step 2/3 Ontology, formula chain, lineage (AI authored)
03_verify/ Step 4 Report + row detail + workbook exceptions + verify_result.json
05_graph/ Step 4b ontology.json + ontology.mmd + ontology-report.md
04_output/ Step 5 Result Excel + analysis report + whatif.json
06_dashboard/ Step 6 dashboard.html (single shareable file)
07_blame/ E1 Reverse fault-isolation report
08_sensitivity/ E1 Sensitivity-ranking report
09_merge/ E1 Cross-workbook ontology merge candidates
10_links/ M External-link graph with broken and circular references
11_masked/ M Shareable structure package + MANIFEST self-check; raw occurrences must be 0
12_reconcile/ M Two-definition reconciliation: routing layer + attribution candidates
13_questions/ M Open-question list for business experts
spec.json Formal AI interpretation of the business logic
Never modify the user's original workbook. Write every artifact to a separate output directory.
12 · Program structureData contract: spec.json
spec.json is the only interface between AI and the tool. Minimal skeleton:
{
"workbook": "/abs/path/workbook.xlsx",
"sheet": "Payroll Detail",
"header_rows": 4, // Header depth; one wrong row invalidates the model
"keys": {"ID": "Employee ID", "NAME": "Name"}, // Column label or zero-based index
"dimensions": {"DEPT": "Level 1 Department"},
"fields": {"A": "Base Salary A", "B1": 36, "G_x": "Gross Pay G"},
"derived": {"B": "B1+B2+B3", "C": "C1+C2"}, // Evaluated in declaration order (topological order)
"checks": [
{"name": "Gross Pay G", "target": "G_x", // target = existing Excel result column
"expr": "round(A+B-C+D+E-F, 2)", "tolerance": 0.01}
],
"table_checks": [{"type": "unique", "name": "Employee ID unique", "fields": ["ID"]}],
"skip_when": {"empty": ["ID"], "label_in": ["Summary", "Subtotal", "Total"]}
}
Complete field reference
| Field | Required | Description |
|---|---|---|
workbook | ✅ | Absolute Excel path |
sheet | ✅ | Primary sheet name |
header_rows | ✅ | Header depth; data starts at zero-based row header_rows |
keys | ✅ | Primary-key or identity columns as {alias: column reference} |
fields | ✅ | Columns used in calculations as {alias: column reference} |
dimensions | Analysis-dimension columns | |
derived | Intermediate values as {alias: expression}, evaluated in declaration order | |
checks | Array of row-level checks. May be empty for a formula-free workbook | |
table_checks | General workbook-level checks | |
skip_when | Row-exclusion rules that also determine which rows remain available to total_row as totals | |
cross_checks | Cross-sheet field-transfer consistency | |
lineage / ontology | Lineage and ontology written to corresponding sheets in the result workbook | |
object | {"name":"Payroll Record","grain":"one person per month"}, used by graph | |
unverifiable | Declares a path that cannot be calculated and why, so What-If reports it instead of forcing a result | |
analysis | Analysis configuration used by analyze | |
_meta | Profile information and TODOs written by scaffold; ignored by verify |
Column-reference rules
"fields": {
"A": "Base Salary A", // String: exact match first, then containment, against joined headers
"B1": 36, // Integer: zero-based column index, the safest option
"G_x": "Gross Pay G" // Existing Excel result column compared with the AI result
}
If a string matches multiple columns, fail immediately and list the candidates. This is deliberate: silently selecting the first match can verify the wrong column without any warning.
Expression syntax and security boundary
derived, checks[].expr, the left/right fields in table_checks,
analysis.rules[].when, and what_if[].set share one restricted evaluator.
✓ Allowed
- Arithmetic
+ - * / ** %, parentheses, unary minus- Comparison
== != < <= > >=- Logic
and or not- Conditional
x if cond else y- Functions
abs round min max int float sum floor ceil- Variables
- Aliases from
keys/dimensions/fields/derived
✗ Prohibited: throw an error, never execute silently
- Attribute access
- Subscripts
- Imports
- Any function outside the allowlist
The implementation uses an AST allowlist traversal, not blacklist filtering. Future Python syntax therefore cannot be enabled accidentally.
Numeric-conversion rules
| Source value | Converted result |
|---|---|
12345.67 | 12345.67 |
"1,234.56" | 1234.56 |
"(1,234)" | -1234.0—accounting-negative notation must be recognized |
"85%" | 85.0—note that it is not divided by 100 |
"/" "-" "—" "\u4e0d\u9002\u7528" "\u65e0" | 0.0; the escapes represent localized “not applicable” and “none” tokens |
Empty / NaN / None / unparseable text | 0.0 |
Common expression patterns
"expr": "round(A + B - C, 2)" // Keep two decimal places
"expr": "ACT/TGT if TGT else 0" // Divide-by-zero guard
"expr": "0.10 if ACH >= 1.2 else (0.08 if ACH >= 1.0 else (0.05 if ACH >= 0.8 else 0))"
"expr": "min(max(BASE, 3500), 28000) * 0.08" // Lower and upper bounds
"when": "COEF == 0 and B1 > 0" // Business-rule exception
13 · UsageThree ways to use it
Use it conversationally in Cowork or Claude
Drop the .skill file into the conversation, select “Save skill,” then attach an Excel workbook and ask:
AI follows the six-step method and asks for business definitions at the relevant decision points.
You need to do only two things: answer definition questions and, after verification, help decide whether the interpretation is wrong or the workbook is wrong.
Run it from the command line
Use this mode when a spec.json already exists and the process must rerun each month. Complete the full workflow once,
then change the path and run the last three steps in later periods.
verify exit codes connect directly to CI or scheduled jobs:
0 = pass, 1 = completed with issues, 2 = refused to run. Refusal is not failure: when a precondition is false, no conclusion is produced. Examples include a TODO in the spec, an unresolved alias, or a misconfigured rule.
Use only the methodology
excel_ai.py is one implementation of the method.
If Python cannot be installed or the workflow must join an existing platform, reimplement the
required behavioral specification from the relevant section of SKILL.md in another stack.
These requirements cannot be omitted: join multi-row headers and expand merged cells, extract formulas with data_only=False,
use AST allowlist evaluation, convert non-numeric values to 0.0, fail when one label matches multiple columns, and retain label_in rows for total_row.
14 · UsageCommand-line reference
| Subcommand | Step | Purpose | Output |
|---|---|---|---|
profile | 0 | Profile archetype and structure | 00-profile-report.md + profile.json |
tomd | 1 | Excel → structured Markdown | One .md per sheet + 00-index.md |
scaffold | 1b | Generate a draft spec | spec.draft.json |
verify | 4 | Row verification + workbook checks + cell provenance | Verification report + three CSV files + verify_result.json |
graph | 4b | Lift an object graph and attribute DAG | ontology.json / .mmd / ontology report |
output | 5 | Generate an annotated result workbook | AI-results.xlsx with 5 sheets |
analyze | 5b | Business-value analysis and What-If | analysis-report.md + whatif.json |
dashboard | 6 | Generate a single-file web dashboard | dashboard.html |
Extensions: E1 logic layer
| Subcommand | Purpose | Output |
|---|---|---|
blame | After verification fails, trace the dependency chain to identify the faulty input | Reverse fault-isolation report |
sensitivity | Perturb each input by 1% and rank the highest-leverage inputs | Sensitivity ranking |
merge | Merge ontologies across workbooks, prioritizing explicit sameas while heuristics produce candidates only | Merged ontology + candidate list |
Management-reporting package (M) · One workflow, many workbooks
| Subcommand | Purpose | Output |
|---|---|---|
links | Cross-workbook external-link graph: broken links, circular references, and large-range references | external-link-graph.md + links.json + .mmd |
mask | Shareable structure package + boundary self-check: zero raw values, or refuse generation | headers/formulas/links + MANIFEST.json |
reconcile | Reconcile two definitions, adding a routing layer and attribution candidates to each difference | Reconciliation report + difference detail |
batch | Run batches across a hundred BUs; one failure does not stop the batch, and failures are marked in the summary | Summary matrix + item-level artifacts |
restate | Restate organizational splits or merges; refuse automatic split restatement without an approved rule | Restated result + conservation check |
questions | Open-question list from TODOs, openQuestions, and unattributed exceptions | open_questions.json + Markdown |
Ontology awareness (E7)
| Subcommand | Step | Purpose | Output |
|---|---|---|---|
context | -1 | Load published ontology context—published only | context.json + context-summary.md |
scaffold --contextwrites published rules intotable_checksautomatically and aligns business aliases to the current workbook using the column mappings saved during preservation. The analyst writes no configuration. Unresolved aliases are named explicitly and never guessed, because a guessed rule could test the wrong column and still return a clean ✅.
# Step 0-1 · Profile and convert to Markdown
python3 scripts/excel_ai.py profile workbook-a.xlsx workbook-b.xlsx -o ./00_profile
python3 scripts/excel_ai.py tomd workbook-a.xlsx workbook-b.xlsx -o ./01_raw_md
# Step 1b · Generate a draft; optional, and must be completed by a person or AI
python3 scripts/excel_ai.py scaffold workbook-a.xlsx --sheet Detail -o spec.draft.json
# Step 4 · Verify: exit 0 pass / 1 issues found / 2 refused because of TODO, alias, or rule configuration
python3 scripts/excel_ai.py verify spec.json -o ./03_verify
# Step 4b · Ontology graph
python3 scripts/excel_ai.py graph spec1.json spec2.json --verify ./03_a ./03_b -o ./05_graph
# Step 5 · Deliver
python3 scripts/excel_ai.py output spec.json -d ./03_verify/verification_detail.csv -o ./04_output
python3 scripts/excel_ai.py analyze spec.json -d ./03_verify/verification_detail.csv -o ./04_output
# Step -1 · Load published ontology and inject rules for zero-config reuse next period
python3 scripts/excel_ai.py context --registry ./registry --domain mreport -o ./ontology
python3 scripts/excel_ai.py scaffold management-report.xlsx --context ./ontology/context.json -o ./specs
# Management reporting · many workbooks; inspect external links first
python3 scripts/excel_ai.py links management-report.xlsx financial-report.xlsx -o ./10_links
python3 scripts/excel_ai.py mask management-report.xlsx financial-report.xlsx --anonymize-columns -o ./11_masked
# Step 6 · Dashboard
python3 scripts/excel_ai.py dashboard \
--verify ./03_a ./03_b --ontology ./05_graph/ontology.json \
--whatif ./04_a/whatif.json --profile ./00_profile/profile.json --raw-md ./01_raw_md \
--title "Example Project · Excel Reverse-Engineering Dashboard" -o ./06_dashboard/dashboard.html
Automatic What-If propagation through the DAG
The old form required a person to write recompute: ["B","C","D"]. Omit one item and the result is silently wrong.
Now only set is required. The script decides which intermediate values to recalculate, selects affected result columns automatically,
and reports every unverifiable path as unable to simulate instead of forcing a result.
## What-If: increase base salary by 10%
**Changed input**: `A`
**Automatically recalculated intermediate values** in topological order: `INCOME`
> ⚠️ The following path cannot be simulated and is excluded instead of forced:
> `R_net`: net pay needs cumulative tax withholding, but the monthly workbook lacks cross-period state
Gross Pay E total: 152,517.24 → 165,824.50 (+13,307.26)This changes What-If from “it may calculate incorrectly” to “it tells you when it cannot calculate.”
15 · Run guideInstall and run end to end
Dependencies
# Required
pip3 install pandas openpyxl # Some systems require --break-system-packages
# Strongly recommended for formula-cache recalculation and legacy .xls conversion
# macOS: brew install --cask libreoffice
# Ubuntu: apt install libreoffice-calc
# Windows: download the installer from the official website
See the complete workflow with one command
cd excel-ai-analyst
bash examples/run_demo.sh ./demo_run
open ./demo_run/06_dashboard/dashboard.html
The script generates the demo workbook → profiles and converts it to Markdown → writes three specs → verifies them with cell-level provenance → builds the ontology graph → runs analysis and What-If → creates the web dashboard → and finally prints the result of each of the five seeded-issue detection paths.
Use it on your own workbook in nine steps
- Run
profile, then read the matching archetype underreferences/patterns/ - If the structure is not
long, read the relevant section ofreferences/table_shapes.mdand preprocess first - Run
tomdand understand the header structure, input columns, result columns, and check columns - Optionally run
scaffold, then complete the draft: correct aliases, resolve TODOs, and addtable_checks - Write the field ontology and formula chain from the templates in
references/; this step cannot be automated - Run
verifyon the full dataset. The workbook is understood only at 100% row-level pass and zero unexplained workbook-level exceptions - Run
graphto lift the spec into an object graph and attribute DAG - Run
output+analyzefor deliverables and DAG-propagated What-If - Run
dashboardto create a single web file that can be sent directly to colleagues
Rerun each month
sed -i 's|current-month-payroll|next-month-payroll|' spec.json
python3 scripts/excel_ai.py verify spec.json -o ./03_verify && \
python3 scripts/excel_ai.py output spec.json -d ./03_verify/verification_detail.csv -o ./04_output
16 · Run guideAcceptance: all five detection paths must hit
The demo workbook multi_type.xlsx has four sheets covering four structures and archetypes.
Each sheet contains one seeded issue common in real business workbooks. Acceptance requires
all four issues to be found and all five detection paths to hit.
Paths ① and ⑤ detect the same issue: H7 was replaced by a constant.
One issue found by two independent paths demonstrates defense in depth; it must not be counted as two issues.
| # | Sheet | Archetype / structure | Seeded issue | Expected detection path |
|---|---|---|---|---|
| ① | Payroll Detail | payroll / long | Gross pay in row 7 is manually increased by 120 | checks row recalculation |
| ② | Payroll Detail | payroll / long | An employee belongs to “Strategy,” which is absent from master data | foreign_key |
| ③ | Inventory Ledger | inventory / long | SKU-B April opening ≠ March closing, a difference of 37 | continuity |
| ④ | Budget Execution | budget / wide | The Actual Total omits one month | identity horizontal reconciliation |
| ⑤ | Payroll Detail | payroll / long | H7 is a constant while 11 cells in the column contain formulas | Formula breakpoint, the cell-level root cause |
If any path misses, the script, spec, or environment has a problem.
Measured baseline from the v3 demo workbook
| Sheet | Records | Row-level checks | Row mismatches | Pass rate | Workbook-level exceptions |
|---|---|---|---|---|---|
| Payroll Detail | 12 | 12 | 1 | 91.67% | 1 type: foreign_key to Strategy, referenced by 4 rows |
| Inventory Ledger | 18 | 36 | 0 | 100% | 1 type: continuity; SKU-B period 3 closes at 610.00 and period 4 opens at 647.00 |
| Budget Execution | 5 | 10 | 2 | 80.00% | 1 type: horizontal identity reconciliation |
Key payroll location: row 7, csid1003, has gross pay AI=9745.14 / Excel=9865.14 /
difference −120.00. Formula breakpoint H7, with formulas in 11 of 12 cells in the column, is the root-cause location.
Ontology-graph baseline: 4 object types · 1 link · 8 functions, 2 verified · 32 attribute-DAG nodes / 35 edges · 1 path marked unable to simulate.
Workflow-level acceptance: nine checks
| # | Check | Acceptance line |
|---|---|---|
| 1 | Was header_rows confirmed by a person? | Required |
| 2 | Does the spec still contain a TODO? | Must be 0, or verify returns exit code 2 |
| 3 | Row-level pass rate | 100%; attribute every miss individually |
| 4 | Workbook-level exceptions | 0, or each explicitly explained and recorded in a spec comment |
| 5 | Was any tolerance widened? | Not allowed |
| 6 | Are unverifiable paths reported explicitly? | Required through unverifiable; never force a result |
| 7 | Unverified nodes or edges in the ontology graph | Must be marked unverified and drawn with dashed lines |
| 8 | Was spec.json delivered to the user? | Required |
| 9 | Was a plain-language conclusion written, with accountable owner? | Required |
Final report: a plain-language conclusion with an owner
This review covered 3 business sheets, referenced 1 master-data sheet, included 35 records and 58 validation points, and produced row-level pass rates of 91.67% / 100% / 80.00%. It found 4 issues:
1. Gross pay for csid1003 was manually overwritten and is 120 too high; the row formula was replaced by a fixed value. Confirm whether this was an approved supplemental payment. Owner: payroll specialist.
2. “Strategy” is absent from department master data, but 4 employees are assigned to it, preventing cost allocation to a valid cost center. Owner: HR master-data manager.
3. SKU-B has a 37-unit gap between period 3 closing and period 4 opening inventory, indicating an unrecorded gain or transfer. Owner: warehouse operations.
4. The Actual Total formula in the lease-expense row omits June and understates the result by 9,310.24. Owner: budget preparer.Issues 1 and 4 are calculation errors in the workbook that directly affect reported numbers. Issues 2 and 3 are data-management process problems that require additional controls.
17 · Run guideFAQ and common pitfalls
Q · Why are all formula columns empty?
The xlsx file has no cached values, often because it was generated programmatically. Save it once in Excel or LibreOffice:
soffice --headless --convert-to xlsx --outdir /tmp/recalc source.xlsx.
Note that LibreOffice cannot overwrite the source file in place.
Q · Can I continue with a 98% pass rate?
No. A 2% mismatch means part of the interpretation is wrong or part of the workbook is wrong. Both possibilities must be resolved before proceeding.
Q · Why can personal-tax or cumulative fields not be verified?
Cumulative withholding depends on state from January through the current period, which a single-month workbook does not contain. Being unable to recalculate is expected. State which required inputs are missing rather than forcing a result or widening tolerance.
Q · Why not generate the field ontology entirely by script?
Business meaning is not in the file. A script can extract =D4+E4-G4, but cannot infer that column G is the employee share of social insurance
capped by local base limits. AI interpretation and human review are required for that definition.
Q · Why does column matching say “multiple matches”?
Use the column index. This error is deliberate. If the first match were selected silently, the system could verify the wrong column without warning.
Q · What if the business allows a workbook-level exception, such as negative inventory?
Record it in a spec comment so the next run does not require the same judgment. Do not delete the rule merely because the business allows the exception. Keep it, so the exception changes from unknown to known and confirmed.
General pitfall checklist
| # | Pitfall | Response |
|---|---|---|
| 1 | Multi-row headers | Two to four rows are common; count header_rows precisely. One wrong row invalidates everything |
| 2 | Merged cells | Expand merged values before joining column names and skip title rows spanning the whole sheet; the script handles this |
| 3 | “Do not edit or delete formula” | A system-calculated column is a result, not an input; do not feed it into expr as an input |
| 4 | Check columns | They are assertions left by the original author; use them first as verification anchors |
| 5 | /, -, and localized N/A tokens | They mean not participating or not applicable; convert to 0 for calculation but distinguish them from a true business zero |
| 6 | Total and subtotal rows | Exclude them with skip_when.label_in or amounts will double; labels alone may not remove every level of subtotal |
| 7 | Terminated or mid-period hires | They frequently cause verification mismatches and deserve separate review |
| 8 | Floating-point error | Apply round(x,2) at each layer, not once at the end; compare with tolerance, not == |
| 9 | CSV encoding | Always use utf-8-sig so Excel opens the file correctly |
| 10 | Modifying the user's source workbook | Write every artifact to a separate output directory |
| 11 | Formula columns appear empty | No cached values are present; recalculate with soffice --headless --convert-to xlsx |
| 12 | Column names contain one another | Actual Jan can match Actual Jan YTD. Always use column indices in wide tables |
| 13 | Code columns coerced to numbers | 00123 becomes 123, and long codes become scientific notation, breaking every key match |
| 14 | Period-column sorting | continuity sorts strings, so 10 precedes 2. Normalize to a fixed-width form such as 2026-01 |
18Deliverables and roadmap
Deliverables from one analysis
| Artifact | Produced by | Required |
|---|---|---|
spec.json | Steps 2/3/4 | ✅ Highest value |
| Structured Markdown + index | tomd | ✅ |
| Profile report | profile | |
| Field ontology / formula chain / lineage | AI authored | ✅ |
Verification report + three CSV files + verify_result.json | verify | ✅ |
ontology.json / .mmd / ontology report | graph | |
AI-results.xlsx | output | ✅ |
Analysis report + whatif.json | analyze | ✅ |
| dashboard.html | dashboard | |
| Plain-language conclusion | Person / AI | ✅ Delivery endpoint |
Version evolution
| Dimension | v0 original | v1 | v2 | v3 |
|---|---|---|---|---|
| Workflow | Five steps in three separate scripts | Five steps in one tool file | Six steps, adding Step 0 profiling | + Step 4b graph · Step 6 dashboard |
| Subcommands | 3 separate Python files | 4 | 6 | 8 |
| Archetype support | None | Payroll implied as the prototype | Eight pattern libraries | Unchanged |
| Structure support | None | Long tables only | Four structural shapes | Unchanged |
| Verification | None | Formula recalculation only | + thirteen workbook-level rules | + cell-level provenance and formula breakpoints |
| What-If | None | Manual recompute | Same | Automatic DAG propagation |
| Ontology | Field-definition Markdown | None | Column data dictionary with no consumer | Objects / links / functions / attribute DAG |
| Quality guard | None | None | Refuse to run on TODO with exit code 2 | Anything without a green result is unverified |
| Documentation | README + SKILL.md | Same | + offline HTML site + 61-page manual | + single-file dashboard + one-command full workflow |
This table ends at v3; it is not the current state. Later historical deliveries added the E1 logic layer (
blame/sensitivity/merge), management-reporting package M, and the ontology registry. That preserved method baseline reached 18 subcommands, 7 registry commands, 9 archetype libraries, and 19 workbook-level check types. The current stable authority is the 1.34 five-Skill product described on the system architecture page.
Roadmap
Phase two · first three items delivered
- ✅ Merge ontologies across workbooks with
sameAs, shared attribute types, and units—merge - ✅ Reverse fault isolation: after verification fails, trace dependency edges to the deepest consistent node—
blame - ✅ Sensitivity ranking: perturb each input by 1%, measure target Δ, and rank leverage—
sensitivity - DuckDB export for instance-level provenance using one file and recursive CTE—not built
Phase three
- Action Type and governed write-back with preconditions, side-effect declarations, and audit
- Named-scenario persistence and multi-scenario comparison
- Time-versioned ontology
Phase three assumes a governed runtime. Writing back to scattered xlsx files has neither transactions nor an audit surface, so building it now would create a toy. It should wait for a real operating context.