Workspace/Mini projects
Loading progress
All mini projects
MODULE 15 · 5 HOUR BUILD

Inspectable invoice browser workflow

Build a browser workflow harness that records observations, proposals, preconditions, and persisted outcomes. The seed simulates a tiny invoice application without a browser or network.

Build evidence Record your actual checks, results, and limitations.

Build it in stages

  1. Define observation and action schemas with revision and invoice identity.
  2. Add ambiguous controls, hidden controls, and stale-state fixtures.
  3. Implement observe, propose, validate, execute, and verify stages.
  4. Export a claim and action trace for each fixture case.
  5. Optionally replace the simulated page with a local Playwright fixture after installing Playwright and its browser separately.

Your acceptance criteria

Use these as your project review. Record commands, outputs, and failure cases in your repository.

  • A stale proposal performs zero writes.
  • A valid save updates only the selected invoice.
  • Every success includes a checked record value.
  • Ambiguous targets and injected page instructions produce explicit diagnostic records.

A working starting point

The seed runs as supplied. Extend it to satisfy the full brief. It is a teaching starting point, not a finished portfolio submission.

main.py
python
from copy import deepcopy

class InvoiceApp:
    def __init__(self):
        self.revision = 1
        self.records = {'42': {'reference': 'OLD'}, '99': {'reference': 'KEEP'}}
        self.trace = []

    def observe(self, invoice):
        return {'revision': self.revision, 'invoice': invoice,
                'record': deepcopy(self.records[invoice])}

    def save(self, proposal):
        if proposal['revision'] != self.revision:
            self.trace.append('blocked: stale proposal')
            return False
        invoice = proposal['invoice']
        if invoice not in self.records:
            self.trace.append('blocked: unknown invoice')
            return False
        self.records[invoice]['reference'] = proposal['reference']
        self.revision += 1
        verified = self.records[invoice]['reference'] == proposal['reference']
        self.trace.append('verified save: ' + invoice)
        return verified

def main():
    app = InvoiceApp()
    observation = app.observe('42')
    proposal = {'revision': observation['revision'], 'invoice': '42',
                'reference': 'REVIEWED'}
    print('first save:', app.save(proposal))
    print('stale retry:', app.save(proposal))
    print('invoice 42:', app.records['42']['reference'])
    print('invoice 99:', app.records['99']['reference'])
    for event in app.trace:
        print(event)

if __name__ == '__main__':
    main()

Push it further

Add visual fixtures with resized screenshots and measure target selection, coordinate conversion, and final task success as separate outcomes.