Skip to content

ADR 0008: The managed-set is declared in managed.json, not hardcoded

Retired — made moot by ADR 0019. The managed-file set and managed.json no longer exist. Kept for history; not current architecture.

Status: accepted; made moot by ADR 0019 — see Update (single-binary cutover) below.

Update (single-binary cutover)

§

The single-binary cutover removes managed files entirely: with no committed engine to sync, managed.json, the managed-set classifier, and src/lib/manifest.ts are deleted. The "managed vs seed" contract this ADR refined no longer exists — ownership is now yours (committed seeds) vs the binary's (gitignored, re-published artifacts).

Context

§

"Managed vs seed" is the contract that makes upgrade safe: a managed file (bin/agent, .discern/engine/**, .ai/skills/**) is hash-tracked and refreshed by upgrade (preserved as .new when the user edited it), while a seed file (everything else) is write-once. Until now that classification was hardcoded in the installerMANAGED_EXACT / MANAGED_PREFIXES constants in src/lib/manifest.ts.

Two problems with hardcoding it:

  • The contract is invisible from the template tree. What the kit owns is a property of the templates, but you had to read installer source to learn it.
  • An adapter can't own a managed file. add-adapter overlays files through the same plan builder, so an adapter file is managed only if it happens to fall under a hardcoded prefix (.ai/skills/**). An adapter that wants to own a managed file anywhere else had no way to say so.

Decision

§

Move the managed-set into a declaration the template ships, and let the installer read it.

  • templates/managed.json declares the set: { "exact": ["bin/agent"], "prefixes": [".discern/engine/", ".ai/skills/"] }. It is installer metadata, never scaffolded (the plan walker skips it, the same way add-adapter skips adapter.json).
  • manifest.ts exposes a ManagedSpec ({ exact, prefixes }), isManagedBy(path, spec), a DEFAULT_MANAGED_SPEC that mirrors the shipped file (the fallback when no declaration is present, so behaviour is identical either way), and loadManagedSpec(dir) / parseManagedSpec / mergeManagedSpecs. isManaged(path) remains as a thin wrapper over the default for callers without a spec.
  • buildPlan takes an optional managedSpec. setup and upgrade load it from the templates tree; add-adapter classifies an adapter's overlay files by DEFAULT_MANAGED_SPEC merged with the adapter's own managed.json (if it ships one), so an adapter can mark overlay files it owns.

Consequences

§
  • The managed/seed contract is now data in the template tree, not buried in installer code. A kit maintainer adjusts it by editing managed.json.
  • An adapter can declare managed overlay files. They are hash-tracked in the project manifest and preserved-as-.new if edited, so re-running add-adapter won't clobber local edits — the same safety the kit's own managed files get.
  • Honest limitation: upgrade refreshes only the kit's templates, not adapter files (adapters aren't part of the kit tree). So an adapter-managed file is tracked and edit-preserved, but re-applied via add-adapter, not upgrade. Full adapter-aware upgrade would be a separate, larger feature; this ADR does not promise it.
  • Behaviour is unchanged for every existing install: the shipped managed.json equals the old hardcoded set, and the default applies when it is absent.
  • One new metadata file at the templates root, filtered from the scaffold like adapter.json.

Alternatives considered

§
  • Keep the set hardcoded. Rejected: it hides the contract and blocks adapter-owned managed files — the two problems above.
  • Record the rule in the project manifest instead of the template. The manifest already lists the managed files (paths + hashes), but setup must classify new files from the template walk before any manifest exists for them, so the rule has to come from the template. The template declaration is the right source of truth; the manifest stays a record of what was written.
  • A glob engine for the spec. Overkill: the managed set is a handful of exact paths and directory prefixes. Prefix/exact matching is enough and keeps the classification trivial to reason about (it mirrors what the old constants did).
  • Let an adapter's managed.json fully replace the base spec. Rejected: merging keeps the kit's defaults (so an adapter's skills stay managed) while letting the adapter add its own — replacing would surprise an adapter author by un-managing the standard trees.
choose openEsc close