NEO.K / MSSP FIELD LAB008-compatibility-alias
編號008-compatibility-alias
語言javascript
版本v1.0
日期2026-08-08
行數711
執行node src/main.js

008 — A rename is a third kind of edge, and here is the counter-example that proves the check works

This example is candidate, not adopted method. Module 02's ban on a TMS referencing a sibling TMS is untouched, and scripts/build-mssp.mjs still blocks all four reference forms. Nothing here changes MSSP.

What this program does

It runs three lint rules over a fixture, resolves one name through a declared rename, and then checks every declared rename against what the code actually does.

node src/main.js            # the declarations, checked
node src/main.js --strict   # exit 1 if any declaration does not hold
node src/main.js --shims    # what the host-shim generator would emit
node src/island_test.js     # 24 checks across 7 sections
$ node src/main.js

== declared compatibility aliases  (current version 2.4.0)

  ok  rules/imports-first -> rules/first   window 2.0.0..3.0.0
      observer rule-contract-v1, allowed deltas: meta.deprecated, meta.description
      permitted      meta.deprecated: true -> undefined

  !!  rules/legacy-strict -> rules/strict   window 1.4.0..2.0.0
      observer rule-contract-v1, allowed deltas: meta.deprecated, meta.description
      NOT PERMITTED  findings: ["3:var is not permitted","5:use strict appears…"] -> ["5:use strict appears…"]
      permitted      meta.deprecated: true -> undefined
      PROBLEM  findings differ
      PROBLEM  past sunset 2.0.0 (current 2.4.0)

  declared 2, holding 1, broken 1: rules/legacy-strict

The structural decision

A rename is not a reference. It is a third kind of edge — declared outside the unit, carrying a lifecycle and an equivalence contract someone had to write.

This comes out of mssp-d-001, where 缺點 7 got reframed by Metron in a way I had not reached on my own:

現在的檢查把「A 取用 B 的能力」與「舊名字 A 暫時投影到新名字 B」都畫成同一條兄弟引用邊, 但兩者的責任、生命週期和刪除條件其實不同。這不是先找一種安全的 import 寫法就能解的問題, 而是目前的模型少了一種關係。

I had been asking which syntax to permit. That question has no good answer, because both syntaxes express both relations. The model was short a noun.

Metron also killed the condition I was least sure of, and killed it for a better reason than the one I had:

「兩者公開介面相同」不能作為一般性的完整機械判準。 …這裡兩個物件甚至刻意不完全相同, 因為舊名必須多出 deprecated: true。如果要求整體相等,合法別名反而必然失敗。

So the record does not claim the two are the same. It names an observer, and lists in advance the differences that are permitted:

{
  "kind": "compatibility_alias",
  "old_name": "rules/imports-first",
  "replacement": "rules/first",
  "host_constraint": "a host API that takes one object per public name cannot express 'this name is the old name of that one'",
  "shim": "generated into build/host-shims/, never authored under TMS/",
  "valid_from": "2.0.0",
  "equivalence": { "observer": "rule-contract-v1", "allowed_deltas": ["meta.deprecated", "meta.description"] },
  "evidence": "src/island_test.js section 2",
  "sunset": "3.0.0"
}

A person decides three things and the run can check none of them: which behaviours to observe, which differences are permitted, and when the old name may go. The run checks whether reality matches. That is the same division 範例 007 arrived at yesterday from a different direction — mechanisation does not decide what "the same" means; it verifies whether reality matches a sameness someone declared.

The host-constrained case does not need an exception

When a host API insists on one object per public name, the old name needs a physical file. That file is generated from the record into build/host-shims/, never authored under TMS/ — so no authored unit references a sibling, and module 02 needs no carve-out. Section 2 checks that the authored file genuinely does not exist.

The island test

$ node src/island_test.js
  ... 24 checks across 7 sections ...
  island test passed

Section 1 checks that all four authored rules reach nothing, including the legacy alias — which is the uncomfortable part: it satisfies module 02 completely, and module 02 has nothing to say about whether it is still equivalent. Section 6 checks that SCL owns the compatibility window rather than the unit. Section 7 checks that the record says it is a candidate.

Sections 4 and 5 are the counter-example Metron asked for.

The counter-example

Metron named the validation this example exists to perform:

刻意製造一個「宣告為別名但行為已漂移」的反例,證明契約檢查真的會失敗。

TMS/rules/legacy-strict.js is declared in FMS as an alias of rules/strict. It is not one. Someone added a second condition years after the rename — it also objects to var, and the replacement does not. It references no sibling, it passes every structural rule this field lab has, and the declaration that it is equivalent is simply false.

The check rejects it on two independent grounds, and the report keeps them apart:

  PASS  the drifted alias FAILS the contract - findings differ; past sunset 2.0.0 (current 2.4.0)
  PASS  and it fails BECAUSE the findings differ
  PASS  the differing finding is named - the old name objects to var; the replacement does not
  PASS  it is ALSO past sunset, and that is reported separately

Failing is not enough. Yesterday an island test passed on E0753 while claiming to prove something about E0432, so section 4 goes further: it repairs the drift and re-runs.

  PASS  a faithful shim stops the findings complaint - past sunset 2.0.0 (current 2.4.0)
  PASS  so the findings clause is what detected the drift
  PASS  while the sunset complaint survives the repair

The findings complaint disappears; the sunset complaint does not. That is what makes the first result evidence rather than a coincidence.

Section 5 closes the obvious cheat: adding findings to allowed_deltas does not make the alias hold. An equivalence contract that permits behaviour to differ is not a contract, and that is enforced in code rather than asserted in a comment.

Set by set

FMSarchitecture.json: the record, every declared alias, and the observers. It also carries "status": "candidate" and a note saying so, because a file that describes a governance shape should say whether that shape has been adopted.

SCLpolicy.json: who may open or retire a compatibility window, how many major versions one may span, and the current version. Module 06's replacement-before-removal lives here as something a run can check, not as a sentence in a document.

SMSregistry.js resolves names through the record; contract.js checks declarations against behaviour.

TMS — four rules, each importing nothing, one of which has drifted.

DMSreport.js. Every line is the run agreeing or disagreeing with something a person wrote down, under an observer that person also chose.

What this example does not solve

Following 改良點 8, each item says what turning it into a measurement would take.

Source

FMS

FMS/architecture.json
{
  "name": "008-compatibility-alias",
  "what_it_is": "A rule registry where a rename is a declared relation with a lifecycle, and the declaration is checked against behaviour rather than believed.",
  "the_structural_decision": "A rename is not a reference. It is a third kind of edge, declared outside the unit, with an equivalence contract someone had to write and a sunset someone has to defend.",
  "why_this_shape": "mssp-d-001 (2026-08-07). Elenchos found the contradiction; Metron reframed it as a missing relation rather than a syntax to permit, and named two validations before it could be trusted: a rename under a second host interface, and a deliberately drifted alias proving the contract check can fail. This example is the second one.",
  "status": "candidate",
  "note_on_status": "Nothing here is adopted method. Module 02's ban on sibling references is untouched and the build guard is unchanged. This is an experiment that produces evidence for or against the candidate.",
  "compatibility_aliases": [
    {
      "kind": "compatibility_alias",
      "old_name": "rules/imports-first",
      "replacement": "rules/first",
      "host_constraint": "a host API that takes one object per public name cannot express 'this name is the old name of that one', so a physical shim is required",
      "shim": "generated into build/host-shims/, never authored under TMS/",
      "valid_from": "2.0.0",
      "equivalence": {
        "observer": "rule-contract-v1",
        "allowed_deltas": [
          "meta.deprecated",
          "meta.description"
        ]
      },
      "evidence": "src/island_test.js section 2",
      "sunset": "3.0.0"
    },
    {
      "kind": "compatibility_alias",
      "old_name": "rules/legacy-strict",
      "replacement": "rules/strict",
      "host_constraint": "none - this one was authored by hand years ago and has been maintained since",
      "shim": "authored at TMS/rules/legacy-strict.js",
      "valid_from": "1.4.0",
      "equivalence": {
        "observer": "rule-contract-v1",
        "allowed_deltas": [
          "meta.deprecated",
          "meta.description"
        ]
      },
      "evidence": "src/island_test.js section 3",
      "sunset": "2.0.0",
      "note": "This declaration is FALSE and the run says so. It is the counter-example Metron asked for: an alias that drifted, still declared, still passing every structural rule."
    }
  ],
  "observers": {
    "rule-contract-v1": {
      "observations": [
        "findings",
        "meta"
      ],
      "non_waivable": [
        "findings"
      ],
      "what_it_compares": "for each fixture line, the set of findings the rule produces, plus every meta field",
      "what_it_ignores": "nothing by default — allowed_deltas is per-alias and must name an observation listed above",
      "what_it_cannot_see": "timing, memory, anything the rule does that is not a finding or a meta field",
      "note": "observations and non_waivable are read by SMS/contract.js. Metron found on 2026-08-08 that the observer name was only a label — an unresolvable id still returned holds:true. 2026-08-09: implementations now live in SMS/observers.js and are resolved by id; an id with no implementation fails closed."
    },
    "rule-contract-v2": {
      "observations": [
        "findings",
        "meta"
      ],
      "non_waivable": [
        "findings"
      ],
      "what_it_compares": "the same as v1, plus the rule id — so two rules with different ids and identical behaviour are NOT equivalent under it",
      "what_it_ignores": "nothing by default",
      "what_it_cannot_see": "timing, memory, anything that is not a finding or a meta field",
      "why_it_exists": "Metron, 2026-08-09: with one observer, resolving an id and dispatching on it are indistinguishable. A second observer that gives a DIFFERENT verdict on the same pair is what makes the dispatch observable."
    }
  },
  "sets": {
    "FMS": "this file: the architecture record, including every declared rename and the observer it is declared under",
    "SCL": "who may open, extend or retire a compatibility window, and the current version",
    "SMS": "name resolution through the record, and the contract checker",
    "TMS": "rules, each importing nothing - including one hand-authored legacy shim that has drifted",
    "DMS": "which declarations hold, which have drifted, and which are past their sunset"
  },
  "non_goals": [
    "Being a linter. Three rules, a line scanner, no AST.",
    "Deciding what 'the same' means. The observer and the allowed deltas are written by a person; the run only checks reality against them.",
    "Proposing a change to module 02. The ban is untouched here."
  ]
}

SCL

SCL/policy.js
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";

const here = path.dirname(fileURLToPath(import.meta.url));
const config = JSON.parse(fs.readFileSync(path.join(here, "policy.json"), "utf8"));

export const currentVersion = () => config.current_version;
export const enabled = () => [...config.enabled];
export const mayOpenAlias = (actor) => config.may_open_alias.includes(actor);
export const maxWindowVersions = () => config.max_window_versions;

/** Major-version distance, which is all this example's versions need. */
export function majorsBetween(from, to) {
  return Number(to.split(".")[0]) - Number(from.split(".")[0]);
}
SCL/policy.json
{
  "policy_version": "1.0",
  "current_version": "2.4.0",
  "_comment": [
    "A compatibility window is an authority question, not a structural one:",
    "who may open one, how long it may run, and who may retire it. Module 06's",
    "replacement-before-removal lives here, as something a run can check."
  ],
  "may_open_alias": ["maintainer"],
  "may_retire_alias": ["maintainer"],
  "max_window_versions": 1,
  "enabled": ["rules/imports-first", "rules/legacy-strict", "rules/no-self-import"]
}

SMS

SMS/contract.js
// Checking a declared equivalence, rather than inferring one.
//
// Metron's point in mssp-d-001: "兩者公開介面相同" cannot be a general
// mechanical criterion. In a dynamic language the full interface includes
// behaviour, errors, metadata and side effects, and here the two objects are
// DELIBERATELY different — the old name must carry deprecated: true. Demand
// total equality and every legitimate alias fails; compare only exported keys
// and behavioural drift reads as equality.
//
// So the machine does not decide what "the same" means. It checks whether
// reality matches a sameness someone declared, under a named observer, with the
// permitted differences written down in advance.

import { record } from "./registry.js";
import { resolveImplementation } from "./observers.js";

// Metron ran this on 2026-08-08 with observer: "observer-that-does-not-exist"
// and got {holds: true, problems: []}. The observer name was a label — the
// function always called the one hard-coded comparator below, so what this
// file proved was "this comparator passes", not "the declared contract holds".
// In an example whose entire claim is that a declaration must be checked, the
// declaration was not checked. It now fails closed.
function resolveObserver(alias) {
  const name = alias?.equivalence?.observer;
  if (!name) return { problems: ["no observer named in the equivalence clause"] };
  const observer = record.observers?.[name];
  if (!observer) {
    return { problems: [`observer "${name}" does not resolve in FMS — fail closed`] };
  }
  // Metron, 2026-08-09: resolving the id was not enough. The verdict has to be
  // produced BY the implementation that id names, or the check still only
  // proves "the one comparator in this file passes".
  const bound = resolveImplementation(name);
  if (bound.problem) return { problems: [bound.problem] };

  const problems = [];
  for (const delta of alias.equivalence.allowed_deltas ?? []) {
    const head = String(delta).split(".")[0];
    if (!observer.observations.includes(head)) {
      problems.push(`allowed_delta "${delta}" is not an observation of ${name}`);
    }
    if (observer.non_waivable.includes(head)) {
      problems.push(`"${delta}" names ${head}, which ${name} declares non-waivable`);
    }
  }
  return { observer, observe: bound.implementation, problems };
}

export function checkAlias(alias, oldRule, newRule, fixture, currentVersion, majorsBetween, maxWindow) {
  const problems = [];

  // Fail closed before anything is compared. A contract whose observer cannot
  // be resolved has not been checked, and reporting "holds" for it is worse
  // than reporting nothing.
  const resolved = resolveObserver(alias);
  problems.push(...resolved.problems);
  if (!resolved.observer) return { alias, holds: false, problems, deltas: [] };

  if (!oldRule) problems.push(`the old name has nothing behind it`);
  if (!newRule) problems.push(`the replacement ${alias.replacement} does not exist`);
  if (problems.length) return { alias, holds: false, problems, deltas: [] };

  const before = resolved.observe(oldRule, fixture);
  const after = resolved.observe(newRule, fixture);

  // Behaviour is never in allowed_deltas by construction: the observer's whole
  // purpose is that findings must agree. Saying otherwise would make the
  // contract unfalsifiable, which is the shape this field lab keeps finding.
  const deltas = [];
  if (before.findings.join("|") !== after.findings.join("|")) {
    problems.push("findings differ");
    deltas.push({ field: "findings", old: before.findings, new: after.findings });
  }

  const keys = new Set([...Object.keys(before.meta), ...Object.keys(after.meta)]);
  for (const key of keys) {
    const path = `meta.${key}`;
    const a = JSON.stringify(before.meta[key]);
    const b = JSON.stringify(after.meta[key]);
    if (a === b) continue;
    if (alias.equivalence.allowed_deltas.includes(path)) {
      deltas.push({ field: path, old: before.meta[key], new: after.meta[key], allowed: true });
      continue;
    }
    problems.push(`${path} differs and is not in allowed_deltas`);
    deltas.push({ field: path, old: before.meta[key], new: after.meta[key] });
  }

  // Module 06 as something a run can check: replacement before removal, and a
  // window that does not outlive the policy's limit.
  const overdue = majorsBetween(alias.sunset, currentVersion) >= 0;
  if (overdue) problems.push(`past sunset ${alias.sunset} (current ${currentVersion})`);
  if (majorsBetween(alias.valid_from, alias.sunset) > maxWindow) {
    problems.push(`window ${alias.valid_from}..${alias.sunset} exceeds the permitted ${maxWindow} major(s)`);
  }

  return { alias, holds: problems.length === 0, problems, deltas };
}
SMS/observers.js
// Observer implementations, resolved by the id the record names.
//
// Metron, 2026-08-09, on yesterday's repair:
//
//   現在 resolveObserver() 會確認 id 存在於 FMS;但實際執行仍固定呼叫檔案裡唯一的
//   observe()。… 所以修復目前保證的是「id 必須存在」,還不是「verdict 由該 id 所指
//   的 observer implementation 產生」。
//
// They added a resolvable `different-observer-v2`, pointed an alias at it, and
// got holds: true from the rule-contract-v1 comparator. With one observer that
// is not yet a wrong answer; the moment mssp-d-002 starts versioning observers
// it becomes one.
//
// So an observer is a function here, not a description. An id in the record
// with nothing behind it fails closed, the same way a predicate id does.

import { apply } from "./registry.js";

/** rule-contract-v1: findings per fixture line, plus every meta field. */
function ruleContractV1(rule, fixture) {
  return {
    findings: apply(rule, fixture).map((f) => `${f.line}:${f.message}`),
    meta: rule.meta ?? {},
  };
}

/**
 * rule-contract-v2: the same, plus the rule's own id.
 *
 * It exists so the dispatcher has something to be wrong about. Under v1 two
 * rules with different ids and identical behaviour are equivalent; under v2
 * they are not, and the island test uses exactly that difference to prove the
 * verdict came from the named observer rather than from the only one there is.
 */
function ruleContractV2(rule, fixture) {
  return {
    findings: apply(rule, fixture).map((f) => `${f.line}:${f.message}`),
    meta: { ...(rule.meta ?? {}), id: rule.id },
  };
}

export const IMPLEMENTATIONS = {
  "rule-contract-v1": ruleContractV1,
  "rule-contract-v2": ruleContractV2,
};

export function resolveImplementation(name) {
  const implementation = IMPLEMENTATIONS[name];
  if (!implementation) {
    return { problem: `observer "${name}" has no implementation — fail closed` };
  }
  return { implementation };
}
SMS/registry.js
// Name resolution through the architecture record.
//
// No rule file mentions another rule file. A rename is a row in FMS, resolved
// here, and reported by DMS beside the result it produced.

import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";

const here = path.dirname(fileURLToPath(import.meta.url));
export const record = JSON.parse(
  fs.readFileSync(path.join(here, "..", "FMS", "architecture.json"), "utf8"),
);

export function aliasFor(name) {
  return record.compatibility_aliases.find((entry) => entry.old_name === name) ?? null;
}

export function resolve(requested) {
  const alias = aliasFor(requested);
  if (!alias) return { name: requested, via: null };
  return { name: alias.replacement, via: alias };
}

export async function load(name) {
  const file = path.join(here, "..", "TMS", `${name}.js`);
  if (!fs.existsSync(file)) return null;
  return (await import(`../TMS/${name}.js`)).rule;
}

/** Apply a rule to lines. The walk knows no rule by name. */
export function apply(rule, lines) {
  rule.reset?.();
  return lines
    .map((text, index) => rule.check(text, index + 1))
    .filter(Boolean);
}

TMS

TMS/rules/first.js
// import statements must come before other statements. Imports nothing.
let sawStatement = false;

export const rule = {
  id: "rules/first",
  meta: { category: "order", description: "imports must come first" },
  reset() { sawStatement = false; },
  check(text, line) {
    const trimmed = text.trim();
    if (!trimmed || trimmed.startsWith("//")) return null;
    if (!trimmed.startsWith("import ")) { sawStatement = true; return null; }
    return sawStatement ? { line, message: "import appears after a statement" } : null;
  },
};
TMS/rules/legacy-strict.js
// DECLARED in FMS as a compatibility alias of rules/strict.
//
// It is not one any more, and that is the point of this file. Someone added a
// second condition to the old name years after the rename — a real and common
// thing to happen to a shim nobody re-reads. It imports nothing, it violates no
// structural rule, and the declaration that it is equivalent is simply false.
//
// The run is what says so. Nothing here is marked as the counter-example.
let sawStatement = false;

export const rule = {
  id: "rules/strict",
  meta: { category: "correctness", description: "use strict must come first", deprecated: true },
  reset() { sawStatement = false; },
  check(text, line) {
    const trimmed = text.trim();
    if (!trimmed || trimmed.startsWith("//")) return null;
    if (/^["']use strict["'];?$/.test(trimmed)) {
      return sawStatement ? { line, message: "use strict appears after a statement" } : null;
    }
    // The drift: this old name also objects to var, and the replacement does not.
    if (/^var\s/.test(trimmed)) {
      sawStatement = true;
      return { line, message: "var is not permitted" };
    }
    sawStatement = true;
    return null;
  },
};
TMS/rules/no-self-import.js
// A module must not import itself. Imports nothing.
export const rule = {
  id: "rules/no-self-import",
  meta: { category: "correctness", description: "a module must not import itself" },
  filename: "sample.js",
  check(text, line) {
    const match = text.match(/^\s*import\s[^;]*?from\s+["']([^"']+)["']/);
    if (!match) return null;
    const target = match[1].replace(/^\.\//, "").replace(/\.js$/, "");
    return target === this.filename.replace(/\.js$/, "")
      ? { line, message: `imports itself (${match[1]})` }
      : null;
  },
};
TMS/rules/strict.js
// A file must declare "use strict" before any statement. Imports nothing.
let sawStatement = false;

export const rule = {
  id: "rules/strict",
  meta: { category: "correctness", description: "use strict must come first" },
  reset() { sawStatement = false; },
  check(text, line) {
    const trimmed = text.trim();
    if (!trimmed || trimmed.startsWith("//")) return null;
    if (/^["']use strict["'];?$/.test(trimmed)) {
      return sawStatement ? { line, message: "use strict appears after a statement" } : null;
    }
    sawStatement = true;
    return null;
  },
};

DMS

DMS/report.js
// Which declarations hold, which drifted, and what a reader can conclude.

export function render(results, currentVersion) {
  const lines = ["", `== declared compatibility aliases  (current version ${currentVersion})`];
  for (const result of results) {
    const { alias } = result;
    lines.push("");
    lines.push(`  ${result.holds ? "ok " : "!! "} ${alias.old_name} -> ${alias.replacement}` +
               `   window ${alias.valid_from}..${alias.sunset}`);
    lines.push(`      observer ${alias.equivalence.observer}, ` +
               `allowed deltas: ${alias.equivalence.allowed_deltas.join(", ") || "none"}`);
    for (const delta of result.deltas) {
      const mark = delta.allowed ? "permitted" : "NOT PERMITTED";
      lines.push(`      ${mark.padEnd(14)} ${delta.field}: ${JSON.stringify(delta.old)} -> ${JSON.stringify(delta.new)}`);
    }
    for (const problem of result.problems) lines.push(`      PROBLEM  ${problem}`);
  }

  const broken = results.filter((r) => !r.holds);
  lines.push("");
  lines.push(`  declared ${results.length}, holding ${results.length - broken.length}, ` +
             `broken ${broken.length}${broken.length ? `: ${broken.map((r) => r.alias.old_name).join(", ")}` : ""}`);
  lines.push("");
  lines.push("  a declaration is not evidence. Every line above is the run disagreeing or agreeing");
  lines.push("  with something a person wrote down, under an observer that person also chose.");
  return lines.join("\n") + "\n";
}

root

island_test.js
// The island test, and the counter-example mssp-d-001 asked for.
//
//   node src/island_test.js
//
// Section 4 is the one Metron named: a declared alias whose behaviour has
// drifted must make the contract check FAIL, and it must fail because of the
// drift rather than for some other reason that happens to be true at the same
// time.

import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";

import { checkAlias } from "./SMS/contract.js";
import { aliasFor, load, record, resolve } from "./SMS/registry.js";
import * as policy from "./SCL/policy.js";

const here = path.dirname(fileURLToPath(import.meta.url));
const failures = [];
const report = (label, ok, detail = "") => {
  console.log(`  ${ok ? "PASS" : "FAIL"}  ${label}${detail ? ` - ${detail}` : ""}`);
  if (!ok) failures.push(label);
};

const FIXTURE = [
  '"use strict";',
  'import { a } from "./a.js";',
  "var legacy = 1;",
  "const x = 2;",
  '"use strict";',
];

const check = (alias, oldRule, newRule) =>
  checkAlias(alias, oldRule, newRule, FIXTURE, policy.currentVersion(),
    policy.majorsBetween, policy.maxWindowVersions());

console.log("\n== 1. every authored rule is an island");
{
  const dir = path.join(here, "TMS", "rules");
  const files = fs.readdirSync(dir).filter((f) => f.endsWith(".js"));
  // Four: two current rules, one legacy alias that drifted, and one unrelated
  // rule that exists so the record is not the only thing in the tree. The
  // number is written down so that adding a file without deciding what it is
  // fails here rather than passing quietly.
  report("there are four authored rules", files.length === 4, files.join(", "));
  for (const file of files) {
    const source = fs.readFileSync(path.join(dir, file), "utf8");
    const reaches = [
      /^\s*import\s[^;]*?\sfrom\s+["']([^"']+)["']/gm,
      /^\s*export\s[^;]*?\sfrom\s+["']([^"']+)["']/gm,
      /^\s*import\s+["']([^"']+)["']/gm,
    ].flatMap((re) => [...source.matchAll(re)].map((m) => m[1]));
    report(`rules/${file} reaches nothing`, reaches.length === 0, reaches.join(", ") || "no specifiers");
  }
  // The legacy shim is the interesting one: it is a compatibility alias and it
  // still does not reference the unit it aliases. It reimplements. That is why
  // the structural rule needs no exception and why the drift was possible.
  const legacy = fs.readFileSync(path.join(dir, "legacy-strict.js"), "utf8");
  report("the legacy alias reimplements rather than references",
    !legacy.includes("strict.js") && legacy.includes("use strict"),
    "no sibling reference, so module 02 is satisfied and says nothing about whether it is still equivalent");
}

console.log("\n== 2. a rename is a row in the record, not a property of a file");
{
  const alias = aliasFor("rules/imports-first");
  report("the old name resolves through FMS", resolve("rules/imports-first").name === "rules/first");
  report("and carries its own lifecycle", alias.valid_from === "2.0.0" && alias.sunset === "3.0.0",
    `${alias.valid_from}..${alias.sunset}`);
  report("a current name resolves to itself", resolve("rules/first").via === null);
  report("there is no authored file for the host-constrained old name",
    !fs.existsSync(path.join(here, "TMS", "rules", "imports-first.js")),
    "the host shim is generated into build/host-shims/, outside TMS");
  report("and the record says where it goes", alias.shim.startsWith("generated"), alias.shim);
}

console.log("\n== 3. a declaration that holds, holds for a stated reason");
{
  const alias = aliasFor("rules/imports-first");
  const base = await load(alias.replacement);
  const shim = { ...base, meta: { ...base.meta, deprecated: true } };
  const result = check(alias, shim, base);
  report("the honest alias passes", result.holds, result.problems.join("; ") || "no problems");
  report("and the only difference is one it declared in advance",
    result.deltas.length === 1 && result.deltas[0].field === "meta.deprecated" && result.deltas[0].allowed,
    JSON.stringify(result.deltas));
}

console.log("\n== 4. the counter-example: a declared alias that has drifted");
{
  const alias = aliasFor("rules/legacy-strict");
  const oldRule = await load("rules/legacy-strict");
  const newRule = await load(alias.replacement);
  const result = check(alias, oldRule, newRule);

  report("the drifted alias FAILS the contract", !result.holds, result.problems.join("; "));
  // Not "it failed". Which reason. Yesterday an island test passed on E0753
  // while claiming to prove something about E0432.
  report("and it fails BECAUSE the findings differ",
    result.problems.includes("findings differ"),
    "not merely because something else about it is also wrong");
  report("the differing finding is named", result.deltas.some((d) =>
    d.field === "findings" && d.old.some((f) => f.includes("var is not permitted"))),
    "the old name objects to var; the replacement does not");
  report("it is ALSO past sunset, and that is reported separately",
    result.problems.some((p) => p.startsWith("past sunset")),
    "two independent failures, not one failure counted twice");

  // The verifier verified: remove the drift and the findings clause must stop
  // complaining. If it still complains, the check was reporting on something
  // other than behaviour.
  const faithful = { ...newRule, meta: { ...newRule.meta, deprecated: true } };
  const repaired = check(alias, faithful, newRule);
  report("a faithful shim stops the findings complaint",
    !repaired.problems.includes("findings differ"),
    repaired.problems.join("; ") || "no problems at all");
  report("so the findings clause is what detected the drift",
    result.problems.includes("findings differ") && !repaired.problems.includes("findings differ"));
  report("while the sunset complaint survives the repair",
    repaired.problems.some((p) => p.startsWith("past sunset")),
    "lifecycle and equivalence are independent, and the report keeps them apart");
}

console.log("\n== 5. the contract cannot be satisfied by declaring the drift away");
{
  // The obvious cheat: add findings to allowed_deltas. The observer must refuse
  // it, because an equivalence contract that permits behaviour to differ is not
  // a contract.
  const alias = { ...aliasFor("rules/legacy-strict"),
    equivalence: { observer: "rule-contract-v1", allowed_deltas: ["findings", "meta.deprecated"] } };
  const oldRule = await load("rules/legacy-strict");
  const newRule = await load(alias.replacement);
  const result = check(alias, oldRule, newRule);
  report("listing findings as an allowed delta does not make the alias hold",
    !result.holds, result.problems.join("; "));
  // It now fails EARLIER than it used to. Before 2026-08-08 the refusal came out
  // of the comparison ("findings differ"); the observer now declares findings
  // non-waivable and the contract is rejected at declaration time, before
  // anything is compared. Refusing an unacceptable declaration beats refusing
  // its result, because the result depends on a fixture and the declaration
  // does not.
  report("and it is refused at declaration time, not by the comparison",
    result.problems.some((p) => p.includes("non-waivable")),
    "the observer declares findings non-waivable, so the contract never gets to run");

  // Metron ran this file on 2026-08-08 with an observer id that does not exist
  // and got holds:true — the name was a label and the comparator was hard-coded.
  const bogus = { ...aliasFor("rules/imports-first"),
    equivalence: { observer: "observer-that-does-not-exist", allowed_deltas: ["meta.deprecated"] } };
  const base = await load("rules/first");
  const bogusResult = check(bogus, { ...base, meta: { ...base.meta, deprecated: true } }, base);
  report("an observer id that does not resolve fails closed",
    !bogusResult.holds && bogusResult.problems.some((p) => p.includes("does not resolve")),
    bogusResult.problems.join("; "));

  const offObserver = { ...aliasFor("rules/imports-first"),
    equivalence: { observer: "rule-contract-v1", allowed_deltas: ["timing.ms"] } };
  const offResult = check(offObserver, { ...base, meta: { ...base.meta, deprecated: true } }, base);
  report("an allowed_delta the observer does not observe is refused",
    !offResult.holds, offResult.problems.join("; "));

  // Metron, 2026-08-09: resolving the id was not the same as dispatching on it.
  // With one observer the two are indistinguishable, so the guard is a SECOND
  // observer that reaches a different verdict on the same pair. If the
  // dispatcher were still hard-coded, both rows below would say the same thing.
  const shimWithOldId = { ...base, meta: { ...base.meta, deprecated: true }, id: "rules/imports-first" };
  const underV1 = check({ ...aliasFor("rules/imports-first"),
    equivalence: { observer: "rule-contract-v1", allowed_deltas: ["meta.deprecated"] } },
  shimWithOldId, base);
  const underV2 = check({ ...aliasFor("rules/imports-first"),
    equivalence: { observer: "rule-contract-v2", allowed_deltas: ["meta.deprecated"] } },
  shimWithOldId, base);
  report("the same pair holds under rule-contract-v1", underV1.holds, underV1.problems.join("; ") || "no problems");
  report("and FAILS under rule-contract-v2", !underV2.holds, underV2.problems.join("; "));
  report("so the verdict comes from the observer the record names",
    underV1.holds && !underV2.holds,
    "identical inputs, two observers, two answers — the dispatch is observable");

  const noImpl = { ...aliasFor("rules/imports-first"),
    equivalence: { observer: "declared-but-unimplemented", allowed_deltas: ["meta.deprecated"] } };
  record.observers["declared-but-unimplemented"] = {
    observations: ["findings", "meta"], non_waivable: ["findings"],
    what_it_compares: "nothing — it has no implementation", what_it_ignores: "", what_it_cannot_see: "",
  };
  const noImplResult = check(noImpl, shimWithOldId, base);
  delete record.observers["declared-but-unimplemented"];
  report("an observer declared in FMS with no implementation fails closed",
    !noImplResult.holds && noImplResult.problems.some((p) => p.includes("no implementation")),
    noImplResult.problems.join("; "));
}

console.log("\n== 6. SCL owns the window, not the unit");
{
  report("only a maintainer may open a compatibility window",
    policy.mayOpenAlias("maintainer") && !policy.mayOpenAlias("contributor"));
  report("the permitted window is one major version", policy.maxWindowVersions() === 1);
  const wide = { ...aliasFor("rules/imports-first"), valid_from: "1.0.0", sunset: "9.0.0" };
  const base = await load("rules/first");
  const result = check(wide, { ...base, meta: { ...base.meta, deprecated: true } }, base);
  report("a window wider than policy allows is refused",
    result.problems.some((p) => p.includes("exceeds the permitted")),
    result.problems.join("; "));
}

console.log("\n== 7. what this run does not claim");
{
  report("the record marks itself as a candidate, not adopted method",
    record.status === "candidate", record.note_on_status.slice(0, 60) + "…");
  report("and names the observer's blind spot",
    record.observers["rule-contract-v1"].what_it_cannot_see.includes("timing"),
    record.observers["rule-contract-v1"].what_it_cannot_see);
}

console.log("");
if (failures.length) {
  console.log(`  ${failures.length} check(s) failed: ${failures.join(", ")}`);
  process.exit(1);
}
console.log("  island test passed");
main.js
// Resolve names through the record, then check every declaration against
// behaviour.
//
//   node src/main.js
//   node src/main.js --shims     # what the host-shim generator would emit

import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";

import { checkAlias } from "./SMS/contract.js";
import { load, record, resolve } from "./SMS/registry.js";
import { render } from "./DMS/report.js";
import * as policy from "./SCL/policy.js";

const here = path.dirname(fileURLToPath(import.meta.url));

const FIXTURE = [
  '"use strict";',
  'import { a } from "./a.js";',
  "var legacy = 1;",
  "const x = 2;",
  '"use strict";',
];

async function main(argv) {
  if (argv.includes("--shims")) {
    // The host-constrained case: a name the host must see as its own object.
    // Generated, never authored under TMS/, so no authored unit references a
    // sibling and the structural rule needs no exception.
    for (const alias of record.compatibility_aliases) {
      if (!alias.shim.startsWith("generated")) continue;
      const target = alias.replacement.split("/").pop();
      process.stdout.write(
        `\n  // build/host-shims/${alias.old_name.split("/").pop()}.js  (generated from FMS)\n` +
        `  export { rule as base } from "../../src/TMS/rules/${target}.js";\n` +
        `  // then re-exported with meta.deprecated = true, per allowed_deltas\n`,
      );
    }
    return 0;
  }

  const results = [];
  for (const alias of record.compatibility_aliases) {
    const oldRule = await load(alias.old_name) ?? await shimmed(alias);
    const newRule = await load(alias.replacement);
    results.push(checkAlias(
      alias, oldRule, newRule, FIXTURE,
      policy.currentVersion(), policy.majorsBetween, policy.maxWindowVersions(),
    ));
  }

  process.stdout.write(render(results, policy.currentVersion()));

  // Two different questions want this exit code, and it can only answer one.
  // "Did the report get produced" is the tool's own status; "do the
  // declarations hold" is the finding. Defaulting to the first and putting the
  // second behind --strict means a caller has to say which one it is asking
  // about, instead of a single number quietly meaning whichever the author had
  // in mind. The report says which aliases are broken either way.
  const broken = results.filter((r) => !r.holds).length;
  if (argv.includes("--strict")) {
    if (broken) process.stdout.write(`\n  --strict: exiting 1 because ${broken} declaration(s) do not hold\n`);
    return broken ? 1 : 0;
  }
  return 0;
}

/** A generated shim, materialised in memory: the replacement plus the deltas. */
async function shimmed(alias) {
  const base = await load(alias.replacement);
  if (!base) return null;
  return { ...base, meta: { ...base.meta, deprecated: true } };
}

process.exit(await main(process.argv.slice(2)));