Engineering process · Humans, AI and executable evidence
AI-assisted development of Nift.
Nift is developed with AI as an active implementation and reasoning partner, but not as an authority that can waive evidence. The process combines living repository handovers, bounded checkpoints, independent regression suites, source-level review, reproducible builds and explicit publication boundaries.
An assistant may inspect, hypothesize, implement, benchmark and document. A feature is accepted because its observable behavior survives the appropriate gates—not because generated code or prose sounds confident.
Human-directed agentic engineering
One useful name for this approach is human-directed agentic engineering. The human retains product authority and supplies high-leverage perception and judgement: what problem matters, which trade-offs are acceptable, when a technically successful result still feels architecturally wrong, and what evidence is sufficient for the next checkpoint. Agents can then reason, implement, test, research and attack assumptions at much greater speed inside that direction.
human intent + perception
↓
explicit contracts and bounded task
↓
agent reasoning / implementation
↓
verification + adversarial testing
↓
evidence
↓
human judgement / next direction This is not human micromanagement. A strong agent should challenge questionable assumptions and surface evidence that changes the problem definition. Human direction means the human remains responsible for the goals and acceptance boundary, not that the human dictates every implementation detail.
Source remembers implementation; Git remembers change; tests remember behavioral contracts; benchmarks remember performance expectations; handovers remember transient state and rationale; checkpoints remember what has actually earned trust.
Perception is a high-leverage human contribution
Current agents can be exceptionally strong at reasoning and execution inside a well-framed task while still missing the higher-level signal that the frame itself is wrong. A human may notice that a feature technically works but makes the language harder to explain, that every test passes but the tested assumption is incomplete, or that optimization effort is aimed at an unimportant bottleneck. Good handovers preserve these observations so the next agent knows what deserves attention, not merely what changed.
Why handover documents live in the repositories
Long-running development accumulates knowledge that is not obvious from one source file: architectural intent, historical failures, current risk, release boundaries, validation commands and the reason a tempting design was rejected. Each project therefore carries a concise root HANDOVER.md plus deeper living documents where needed.
| Layer | What it owns |
|---|---|
| Code comment | Local implementation rationale that must remain near the code. |
| Test | Machine-checkable protected behavior. |
| Root handover | Fast orientation, authority, workflow, risks and links to deeper context. |
| Architecture/development/testing docs | System shape, semantic invariants and validation philosophy. |
| Decision record | Why a choice was made and the evidence that should cause it to be revisited. |
| Project history | Chronology and evolving understanding without turning operational docs into a diary. |
| Git history | The exact changes that actually occurred. |
These files are not frozen handoffs from one AI to another. They are maintained throughout the project. Source and tests remain authoritative, uncertainty is recorded honestly, and stale guidance is rewritten or removed rather than preserved ceremonially.
Project memory should be layered rather than dumped into one giant agent prompt: code remembers implementation, Git remembers changes, tests remember protected behavior, benchmarks remember performance expectations, decision records remember rationale and handovers remember the current operational state. The goal is to move important context out of one model session and into durable project artifacts.
The checkpoint loop
reconcile request + repository reality
↓
define one bounded observable contract
↓
add independent/focused tests before implementation
↓
change the smallest correct architectural layer
↓
run focused, full and adversarial validation
↓
inspect performance, safety and generated output
↓
update docs, handovers, roadmap and website claims
↓
commit source and generated publication separately Checkpoints make the state reviewable. A checkpoint is not automatically a release, push, version bump or production declaration. Those remain explicit actions after evidence and diffs are understood.
For Nift itself, a substantial checkpoint is incomplete until the relevant handovers and public reliability claims have been reconciled with the work. In practice that includes reviewing Battle Tested whenever new behavior or regression evidence changes what Nift can honestly claim.
Independent regression suites matter
Nift and tscc have standalone regression repositories that describe behavior without depending on implementation internals. Minify++ has its own independent validation boundary as well as reconciliation between the standalone project and Nift's embedded copy. This separation makes it harder for a patch and its tests to share the same mistaken assumption.
Focused source-tree tests are still essential because they localize failures. The two layers answer different questions: “which component broke?” and “does the product still honor its external contract?”
Contract-based testing
A contract is a statement about behavior that a user, integration or compatible implementation may rely on. Contract tests are written at that boundary instead of mirroring Nift's current classes, helper names or call graph. This lets internal architecture improve without weakening the promise and lets an independent suite test more than one implementation.
given project state + tracked inputs + configuration
when a documented Nift command runs
then outputs, diagnostics, metadata, dependencies,
exit status and filesystem effects match the contract Examples of Nift contracts
| Surface | Observable contract |
|---|---|
| Template composition | @input inserts the resolved source, records the dependency and reports controlled errors for invalid paths or recursion. |
| Checked paths | @pathto emits the correct relative path and records a requirement whose later absence makes the page eligible for rebuild. |
| Project contracts | A configured contract namespace resolves through $[...], cannot be shadowed, and records both its declaration and source as dependencies of outputs that use it. |
| Incremental builds | Changed dependencies rebuild affected outputs; unrelated outputs remain untouched; status explains the same decision without writing. |
| Minification | Selected final-output extensions are minified after rendering; failure does not overwrite the last successful output or metadata. |
| CLI/filesystem | Invalid commands/configuration fail clearly, path containment is respected and destructive operations remain within the requested project target. |
Contract tests differ from implementation tests
A unit test may assert how a parser function classifies one token sequence because that helps localize a defect. The independent contract should instead assert the rendered bytes, recorded dependency, build reason, diagnostic or exit status visible at the product boundary. Both are valuable; only the latter should survive a complete internal rewrite unchanged.
Test the negative and stateful parts of the promise
Good contracts include failure behavior and transitions, not only successful output. Nift cases therefore ask whether a failed build preserves the previous artifact, whether metadata is refreshed only after success, whether missing requirements schedule an authoritative rebuild, whether changing minification policy is itself a rebuild reason and whether repeated incremental checks settle to “up to date”.
Contracts are executable scope control
AI can easily infer a broader promise from one successful example. A contract suite makes the supported boundary explicit: accepted forms, rejected forms, option combinations, filesystem effects and known exclusions. New behavior begins as a proposed contract, receives adversarial neighbors, and becomes part of the permanent suite only when the project is prepared to maintain it.
Changing a contract is not “fixing the test”
When implementation and contract disagree, first determine whether the code regressed, the oracle/environment drifted, or the intended public behavior truly changed. An intentional change must reconcile the independent suite, focused tests, docs, handovers, migration guidance and any versioned metadata. This prevents a convenient expected-output edit from silently redefining the product.
Nift's testing ladder
Parser and templating
Escaping, metadata, parameters, paths, JSON, control flow, nested input and malformed forms receive focused cases.
Filesystem and incremental
Build metadata, dependency fan-out, missing requirements, modified/hash/hybrid behavior and cache refresh are exercised end to end.
Integrated minification
Generated HTML/CSS/JS and other supported artifacts are minified only after successful rendering and committed non-destructively.
Real websites
The Nift, Minify++ and tscc sites dogfood templates, checked paths, multi-extension outputs, minification and the two-branch publication workflow.
Source and generated branches stay distinct
These websites use a deliberate publishing model: stage owns canonical content, templates, configuration and handovers; main owns the built site. On stage, public/ is an embedded checkout of main.
edit canonical source on stage
↓
build with Nift into public/main
↓
inspect and test generated output
↓
commit generated main
↓
commit source + matching Git-link pointer on stage This makes the deployed branch simple without pretending generated HTML is the development source. Static CSS and JavaScript can also be tracked Nift outputs, so readable source participates in dependency tracking and optional final-output minification.
Human-first design that also produces strong AI DX
Nift is first and foremost designed for humans building websites. Its compact model, explicit configuration, deterministic behavior, fast feedback and checked relationships are human developer-experience choices. Those same properties happen to make it unusually legible to coding agents: tracked outputs, templates, @content, @input, @pathto, metadata and incremental dependencies explain most projects. Fast builds make repeated edit/build/inspect cycles cheap, while nift status explains why a page would rebuild before changing output.
The small mental model does not eliminate responsibility. An AI assistant still needs to read the project's handover, inspect current Git state, preserve unrelated user work, distinguish source from generated output and validate links/assets rather than assuming a successful command means a correct site.
What AI should not decide silently
- whether a compatibility boundary should expand;
- whether a benchmark justifies a universal performance claim;
- whether a generated branch should be published;
- whether a checkpoint deserves a release or production label;
- whether uncertain historical artifacts can be deleted.
AI can gather evidence and make trade-offs concrete. Product direction, release authority and irreversible actions remain explicit decisions.
The goal is a development system in which context survives, hypotheses are cheap, contracts are executable, claims stay honest and either a human or a future agent can resume without reconstructing the project from folklore.