Skip to content
← Documentation

docs/platform-boundary.md


The platform boundary — a measured inventory

Not a packaging plan. This asks which concepts belong to Cognithamus, which belong to HQ, and which belong to a consuming application — and states the evidence for each placement. Packaging is downstream of this document and is not discussed here.

Method

Two independent measurements, because either alone misleads:

  1. Import closure — does a module depend on domain? Measured with grep over import specifiers.
  2. Content — does a module contain domain identifiers even when its imports are clean? Measured separately.

plots.ts passes (1) and fails (2). Classifying on imports alone would have placed it on the platform side.


1. Platform concepts — evidence: closed, and universal by inspection

src/core — closed

Measured: core imports nothing outside core. Not one specifier.

Module Concepts
subject.ts SubjectRef, SUBJECT_KINDS, urn
condition.ts CONDITIONS, ConditionId, familyOf
fact.ts Fact (4 families), factIdentity, collapse
evidence.ts Evidence, citeAll
time.ts Instant, Window, Lens
world.ts World, worldAt
ingest.ts Observation, ConnectorManifest, Gap, ingest

The vocabularies are domain-free by inspection, not by assertion:

subjects:   resource, work, actor, agreement, artifact, environment
conditions: unreachable, degraded, unavailable | stalled, blocked, queued,
            abandoned | saturated, overcommitted, idle | unprotected,
            misconfigured, drifted, unverified | exposed, vulnerable,
            unauthorised | overspend, waste, unmonetised

Nothing names code, commits, repositories or agents. Every term applies to a hospital ward, a logistics fleet or a production line without translation.

Derived-geometry mechanics — clean by both measures

metric.ts, layout.ts, allocation.ts, slots.ts, hue.ts import no domain and contain no domain identifiers. They operate on a weighted directed graph over opaque ids:

  • coupling quasi-metric from exchange weights
  • MDS layout with an emitted residual
  • stable allocation guided by the metric, honouring a recorded register
  • ring slot geometry; identity→colour

These are the strongest platform candidates outside core, and unlike core they have a demonstrated consumer need: any application rendering related entities needs proximity that is derived rather than chosen.


2. HQ concepts — belong to the HQ application, not the platform

src/lib/hq — entirely HQ

roster.ts (which agents exist), estate.ts (which products exist), telemetry.ts (which repositories are read), state.ts, findings.ts, view.ts, layout.ts. These are HQ's answers to HQ's questions.

The captured lib/world modules

Measured — these import lib/hq:

Module HQ imports
structure.ts AGENTS, PRODUCTS/Product, RepoStat
build.ts AGENTS, HqState
answers.ts STALE_DAYS
substrate/telemetry.ts STALE_DAYS/HqState, PRODUCTS
substrate/runtime.ts storedTaskKey

This is not misplacement. These are the composition and acquisition layer — exactly where a specific domain should be wired into generic machinery. They are correctly HQ-owned and should never be published.

plots.ts, constitution.ts, amendments.ts

plots.ts is clean by imports and carries HQ instance data: academy, charisma, hq, platform, elite-server, emp, plus agent ids and building names. The mechanism (an append-only allocation register) is platform-shaped; this file's contents are HQ's.

constitution.ts and amendments.ts are HQ's own governance. A consuming application would have its own or none.


3. Enterprise XI concepts

Measured from its fork: PLANS, COURSE/MODULES, its own db, plus marketplace, pricing and academy surfaces. Cognithamus has no concept of a subscription plan or a course, and must not acquire one.


4. Modules that cross the boundary incorrectly

Only two placements are actually wrong. The rest are correct-but-entangled.

4.1 types.ts — the contract is HQ-shaped (the significant one)

world/types.ts is what every renderer, substrate and projection compiles against. Measured contents:

export type DistrictKind = "civic" | "product";
kind: "alert" | "handoff" | "meeting" | "deploy" | "commit";   // WorldEvent

"deploy" and "commit" are software-delivery concepts in the shared type contract. A hospital has no commits. DistrictKind encodes HQ's spatial taxonomy. BuildingKind likewise enumerates hall, library, datacenter, security.

This is the exact defect Article V already caught once, in a different guise: tests/actor-identity.test.ts forbids world/types.ts importing HQ's roster, because "the contract must not depend on a tenant roster." The import was removed; the taxonomy was not. The test enforces the letter and the vocabulary still carries the domain.

4.2 lib/hq/view.ts imports lib/world — the cycle

lib/world imports lib/hq in five modules and lib/hq/view.ts imports back. Neither is a layer; they are one component in two directories. Any extraction must break this cycle first, and it cannot be broken by moving files alone.


5. The three-application test

Would a hospital, a logistics fleet and a factory need each concept?

Concept Hospital Fleet Factory Verdict
SubjectRef, urn platform
CONDITIONS (20 ids) platform
Fact, factIdentity, collapse platform
Evidence, citeAll platform
Lens, worldAt (bi-temporal) platform
ingest, Gap, ConnectorManifest platform
coupling metric / layout / residual platform
source: live | unreachable | not-wired platform
DistrictKind, BuildingKind application
WorldEvent.kind incl. deploy/commit application
AGENTS, PRODUCTS, RepoStat application
PLANS, COURSE Enterprise XI

The test is a thought experiment and is labelled as one. Its value is that it separates concepts by a criterion other than what this repository happens to contain — which is the failure mode of inferring a boundary from one consumer.


6. The smallest stable public API

Ordered by strength of evidence, not by usefulness.

Tier 1 — publish first. The provenance contract: source: "live" | "unreachable" | "not-wired". Copied verbatim and unmodified by the only real consumer; domain-free; it is what stops a dashboard rendering zero as a fact. A type and an invariant, not a module.

Tier 2 — the ontology. SubjectRef/urn, ConditionId/familyOf, Fact/factIdentity/collapse, Evidence, Lens/worldAt, Observation/ConnectorManifest/Gap/ingest. Universal by inspection, closed by measurement, heavily verified — but zero measured demand: the one consumer took none of it.

Tier 3 — derived geometry. The coupling metric, layout with residual, and stable allocation. Clean by both measures, and the plainest need an application has. Depends on nothing above except opaque subject ids.

Excluded from any public surface: types.ts as it stands, structure.ts, build.ts, answers.ts, both substrates, plots.ts contents, constitution.ts, amendments.ts, all of lib/hq.


7. What this does not resolve

  • types.ts must be split before anything ships. A publishable World cannot enumerate "commit". Whether the split is a generic core plus an application-supplied taxonomy, or two separate types, is undecided.
  • The lib/worldlib/hq cycle must break first, and moving files will not break it.
  • Tier 2 has no demonstrated demand. Publishing an unrequested interface creates a compatibility obligation with no corresponding benefit. It is listed because it is correct, not because it is wanted — and those were conflated once already.
  • Package versus API is untouched here, deliberately.