Inspiration
Small finance teams keep invoices and POs as PDFs in shared folders. Many run without an ERP. At month-end, someone asks why an invoice was paid. The controller reopens files by hand. A spreadsheet lists the amounts. It does not show what was checked. It does not show what is still open. I wanted one page that answers the question and points at the line it came from.
What it does
One run reads two NAS folders and writes a close workpaper. The workpaper lists each invoice with what was compared and the page that proves it, and marks a check with no usable quote as unverified. Five checks cover supplier name, PO number, line quantity, unit price, and total. Each check returns one outcome and one evidence status. The two are counted apart. Every undetermined check gets a reason code.
When an earlier pack is supplied, the run compares against it. It records the same bytes, a repeat, or a possible repeat. A changed source keeps both hashes and both run dates. A new invoice, or one that has gone missing, is labelled too.
How we built it
SKILL.md is Markdown. It hands work to three registered agents. Filesystem handles the file list and hashes. Document handles text, matching, and page location. Knowledge handles the approved write. The parent runs no CLI. Every action comes from the public catalog (Uliya Skill Kit 0.7.3, catalog v2.0.0).
Sources stay read-only. The workpaper is written once, after approval. The run reads it back to confirm the counts.
Challenges we ran into
The hard part was not matching numbers. It was deciding what counts as proof. A file can be readable while a field has no usable quote. So outcome and evidence became two counters.
Two runs on the same day collide on the file name. A third run has to see the second run's file, or it will overwrite it. A changed source needs the earlier invoice's path, not just its hash. The return fields had to carry it.
Supplier names vary by legal form and punctuation. Guessing a match is worse than leaving it open. When no PO number matches, one PO from the same supplier becomes a candidate pair. Two or more become undetermined.
Accomplishments that we're proud of
The part worth keeping is the evidence split. A check can return matched and still be unverified, because the document returned no usable quote. The workpaper counts the two apart, so the page never claims a citation it does not have.
Nine reason codes make an exception actionable. An invoice that cannot be matched says why: no PO, a poor scan, a currency difference, or a supplier it cannot confirm.
The same-day fix came out of review. The first version searched the exact output name, so a third run that day could overwrite the second run's file. The search is by prefix now.
No capability in the package is invented. Every action is cited from the catalog, and where the catalog is silent, the package says so. Six synthetic fixtures state the expected result for each case, so the first run on the NAS has something to check against.
What we learned
A match without a quote is not proof. A careful rollup is what a reviewer expects. An invoice with any open check is never called matched. Reason codes matter more than prose. They turn an exception into a task.
I also learned that a claim I cannot check costs more than it earns. Writing "not yet tested on UGREEN AI NAS" into the status section is uncomfortable. It is also the line a judge can check.
What's next for AP Close Pack
Testing on the NAS as a finalist, scan guidance for poor copies, and timing on real document sets.
Built With
- ai
- kit
- markdown
- nas
- skill
- ugreen
- uliya