Week 4 · Takeoff · Lesson 4 of 5

Automating Work Beyond Code

Original outline: John Lindquist · THU · NOV 19, 2026

Independent lesson Explanations, examples, and exercises written from public sources. This is not an official MEGA lesson.

Sections in this lesson

Documentation upkeep, meeting follow-up, support triage, and content preparation all contain repeated work that can benefit from automation. Their difficulty often lies in when work starts and where its effects land. This independently written lesson uses Doc Steward to build an event-driven documentation pipeline. It draws on public automation and hook material; it does not reproduce MEGA lesson bodies or claim access to inaccessible demonstrations.

Learning goals

Find the smallest useful pipeline

John Lindquist's Markdown-link automation post describes a short pipeline: capture selected text, combine it with the browser URL, and copy a Markdown link. Its value comes from removing friction in a repeated writing task. We can apply the same decomposition to a larger service without assuming every step needs AI.

Doc Steward starts with an API-change event, obtains an immutable diff, identifies affected guides, creates a patch, checks it, and prepares a review artifact. Parsing an event envelope and validating a repository identifier are deterministic steps. Deciding whether a behavior change invalidates an explanation may benefit from model judgment. Rendering a source manifest should be deterministic again.

Separate these stages so retries occur at the right boundary. If rendering fails, do not rerun the research automatically. If reference retrieval fails, do not discard a valid event receipt. A pipeline is easier to operate when each stage has a clear input, output, and recorded status.

John's application-specific Alfred snippets show another useful pattern: capture a concrete piece of context and route behavior from it. Our extension is to use authenticated event fields and pinned task metadata rather than whatever application happens to be active.

Hooks attach control to a lifecycle

A hook runs at a defined point in an existing runtime. An external webhook is an incoming notification from another system. They can connect, but they do different jobs. A repository event may enqueue Doc Steward; a runtime hook may validate a tool action inside the worker.

John's claude-hooks repository provides typed TypeScript handlers and generated configuration for Claude Code hooks. Its public README lists Bun as a runtime requirement. Type definitions improve development feedback, but an adapter still needs to match the installed runtime's actual payload and response contract.

The official Claude Code hooks reference documents lifecycle timing and event-specific decisions. PreToolUse runs before a tool call and can block it; PostToolUse runs after success. A post-action check cannot prevent an effect that has already occurred. Use pre-action enforcement for forbidden writes and post-action checks for validation or observation.

A stop hook can be useful for final checks, but repeated blocking can create a loop. Bound corrective attempts, record which artifact version failed, and stop when no new evidence appears. A hook that always tells the worker to continue is a way to consume budget indefinitely.

Push systems need durable acceptance

A push system sends an event when something changes. It reduces the need for constant polling, but does not remove delivery failures or duplicate processing. Treat delivery and work completion as separate facts.

GitHub's webhook guidance recommends checking event type and action, validating the source with a webhook secret, responding promptly, and processing work through a queue when appropriate. It also notes that requested redelivery retains the original delivery identifier.

Our receiver first authenticates the raw request, validates a narrow envelope, and atomically stores a durable inbox record. Only then does it acknowledge acceptance. Acknowledging before persistence can lose the task if the process crashes. Doing the entire model workflow inside the HTTP handler can delay the acknowledgment and complicate recovery.

Use two identities. A delivery identifier tracks a particular transport event. A semantic task key combines repository, revision, and job type. Two distinct deliveries describing the same revision may still represent one documentation task. Conversely, one revision may legitimately trigger different jobs. Model that distinction instead of deduplicating on a title or a timestamp.

Backpressure is part of correctness. Bound queued tasks, coalesce obsolete revisions when the contract allows it, and expose rejected or delayed work. A full queue should not quietly drop changes while the dashboard reports a healthy process.

Boundaries apply to every effect

An event payload is data. A source document is data. Neither may redefine the worker's permissions. A guide containing “send this to all customers” cannot authorize a message. Keep tool credentials and destination allowlists outside the model-controlled content.

Distinguish preparing a review artifact from sending it. The former can be a local write with a limited scope. The latter crosses a communication boundary and needs its own recipient, content, authorization, and receipt. The same principle applies to calendar changes, CRM updates, or publishing a knowledge-base article.

Avoid raw string concatenation into shell commands. Pass structured arguments to a restricted adapter, validate paths against the workspace root, and resolve links before enforcing write boundaries. An allowed-looking relative path can escape through traversal or a symlink if the adapter checks only its spelling.

Worked example

The following is original pseudocode for a receiver and worker. It is neither an installed hook script nor a tested webhook implementation.

receive(request):
    verify_signature(request.raw_body, request.signature)
    event = parse_allowed_event(request)
    key = event.repository + ":" + event.revision + ":docs"
    transaction:
        record_delivery_once(event.delivery_id)
        enqueue_task_once(key, event.reference)
    return accepted

process(task):
    claim_with_lease(task)
    evidence = load_pinned_diff(task.reference)
    patch = prepare_doc_patch(evidence)
    enforce_allowed_paths(patch)
    report = check_patch(patch, evidence)
    if report.passed:
        store_review_artifact_once(task.key, patch, report)
    else:
        record_failure(task.key, report)

Send the same event twice. Expected behavior is two observed requests, one delivery record for that identifier, and one semantic task. Send a distinct delivery for the same revision: the delivery log grows, but the task count remains one. These are expected fixture outcomes, not live results.

Crash the receiver after its transaction commits but before it responds. A redelivery is safe because both inserts are idempotent. Crash the worker after storing the artifact. Recovery looks up the artifact by task key and reconciles its receipt rather than producing another artifact.

Now supply an otherwise valid event from an unapproved repository. Authentication proves who sent the event; it does not establish that this repository is in scope. The receiver should reject or quarantine it according to the declared policy before drafting begins.

Practice

Build a local inbox simulation with an event file and a durable task store. Use fake signatures or a test authentication adapter; do not use live credentials. Create fixtures for duplicate delivery, duplicate meaning, unsupported event, and interrupted acknowledgment.

Acceptance criteria:

A correct answer includes a short event log and counts of deliveries, tasks, and artifacts. Those counts should explain why transport history can contain several entries while work occurs once. The rubric also requires an explicit acknowledgment boundary and an explicit publication boundary. A single “success” Boolean cannot express both.

Check your understanding

  1. Why should a post-tool hook not enforce a no-publication rule? Answer: The publication may already have happened; prevention belongs before execution or in the tool's permission boundary.
  2. Why keep delivery and task keys separate? Answer: Transport duplicates and repeated descriptions of the same logical work are different cases.
  3. What does an accepted webhook response prove? Answer: Only the receiver's declared acceptance condition, ideally durable recording; it does not prove task completion.

Sources

Lesson Markdown · Research evidence and access notes