Skip to content

Autophagy: drop eight orphaned type declarations - #490

Merged
philcunliffe merged 1 commit into
masterfrom
autophagy/cleanup-2026-07-30
Jul 30, 2026
Merged

Autophagy: drop eight orphaned type declarations#490
philcunliffe merged 1 commit into
masterfrom
autophagy/cleanup-2026-07-30

Conversation

@philcunliffe

Copy link
Copy Markdown
Contributor

Autophagy idle-tick cleanup (LLP 0036), run against origin/master at 14e2d96.

This PR proposes; a human disposes. It is a draft on purpose. Everything below is
re-runnable evidence, not a summary. No runtime code changed: the whole diff is
type-only declarations plus the two type imports they were the last users of.


Method

Reachability was established by running searches, not by reading filenames.

  1. Import graph. Resolved every relative from '...' / import('...') specifier across
    src/, bin/, hypaware-core/, scripts/, test/ (excluding node_modules/,
    the generated types/ tree, and notes-archive/) and looked for modules with no
    importer. Every hit was a plugin entry point, a smoke flow, a test file, or a
    package exports barrel - i.e. reachable through string-keyed dispatch, not dead.
    No orphan modules.
  2. Exported value surface. Enumerated all 1359 top-level exports and counted
    occurrences of each name tree-wide. 69 had no mention outside their defining file;
    all 69 turned out to be used internally (constants read by their own module,
    helpers called by their own module). None were dead. No export keyword was
    stripped - an export whose value is live is not dead code, and removing the keyword
    would be churn.
  3. Unused locals / imports / unreachable code. Ran the repo's own compiler as the
    authority rather than a hand-rolled scanner:
    • npx tsc -p tsconfig.json --noEmit --noUnusedLocals --noUnusedParameters -> the
      only TS6133 hits are unused function parameters (argv, opts, ctx,
      positional placeholders in test fakes). Those are signature/arity, not dead code,
      and were left alone. Zero unused imports, zero unused local declarations.
    • npx tsc -p tsconfig.json --noEmit --allowUnreachableCode false --allowUnusedLabels false
      -> zero TS7027. No statements unreachable after a return/throw.
  4. Commented-out code.grep -rnE "^\s*//\s*(const|let|var|function|import|export|return|if\s*\(|await|for\s*\(|console\.)"
    over src bin hypaware-core scripts test -> every hit is a prose comment whose
    wrapped line happens to begin with a word like "return" or "import". None.
  5. Type declarations.tsc --noUnusedLocals does not flag exported types, so
    these were scanned separately: for every declaration in every .d.ts, count
    tree-wide occurrences of the bare name. 18 had exactly one occurrence. Ten of those
    were deliberately kept - see Deliberately left behind,
    which is the useful half of this report.

The tree is in good shape. The eight declarations below are the entire harvest.


Removed (8 declarations + 2 imports they stranded)

The evidence command is the same for each, run from the repo root:

grep -rnw '<NAME>'. --exclude-dir=node_modules --exclude-dir=.git \
--exclude-dir=types --exclude-dir=notes-archive

A result of exactly one line - the declaration itself - means no importer, no
@import JSDoc specifier, no test reference, no @ref annotation, no manifest or
markdown mention. -w is load-bearing: it is what keeps WalkthroughResult from
matching the live PickerWalkthroughResult.

src/core/runtime/types.d.ts

Declarationgrep -rnw result
CreateKernelRuntimeArgssrc/core/runtime/types.d.ts:164:export interface CreateKernelRuntimeArgs { (1 hit)
CreateActivationContextArgssrc/core/runtime/types.d.ts:179:export interface CreateActivationContextArgs { (1 hit)
CreatePluginPathsArgssrc/core/runtime/types.d.ts:189:export interface CreatePluginPathsArgs { (1 hit)
ActivatePluginsArgssrc/core/runtime/types.d.ts:219:export interface ActivatePluginsArgs { (1 hit)
ActivatePluginsResultsrc/core/runtime/types.d.ts:227:export interface ActivatePluginsResult { (1 hit)

Corroboration: src/core/runtime/activation.js imports exactly one name from this
module - @import { KernelRuntime } from '../../../src/core/runtime/types.js' (line
24) - and spells its own parameter shapes inline (@param {{ ... }} at line 38 for
createKernelRuntime, @param {object} args + args.* at lines 117-122 for
createActivationContext). src/core/runtime/paths.js imports only from the kernel
contract. These are residue of the paired-.d.ts consolidation in #182 / #183
("Drop function-only paired .d.ts; JSDoc is the source of truth") - function-only
param descriptions that survived the phase that was meant to remove them.

git log --oneline -S'CreateKernelRuntimeArgs' --all shows the same three commits for
all five: 0c522e6 (added), cb67c0f (#182, relocated), ba3ef45 (#183) - and
nothing since.

Cascade check.ActivatePluginsArgs/Result reference PluginActivationEntry
and ActivationResult; both are independently live, so nothing cascaded:

$ grep -rlw PluginActivationEntry . --exclude-dir=node_modules --exclude-dir=types --exclude-dir=notes-archive
src/core/runtime/loader.js
src/core/runtime/types.d.ts
hypaware-core/smoke/flows/{vector_search_local_fixture,iceberg_export_s3_fixture,s3_query_roundtrip,iceberg_export_s3_roundtrip}.js
$ grep -rlw ActivationResult . --exclude-dir=node_modules --exclude-dir=types --exclude-dir=notes-archive
src/core/runtime/boot.js
src/core/runtime/loader.js
src/core/runtime/types.d.ts

ActivationSuccess / ActivationFailure occur only in types.d.ts but are reachable
through the live ActivationResult union, so they stay.

The removals did strand two type imports, which is why the diff touches the import
block. Re-verified after the edit that both had zero remaining references in the file:

  • PluginPaths (from hypaware-plugin-kernel-types.d.ts) - last user was
    CreateActivationContextArgs.
  • SourceWithholdResolver (from ../cache/types.d.ts) - last user was
    CreateKernelRuntimeArgs.

Both names remain heavily used elsewhere in the repo; only this file's import of them
is gone. ExtendedQueryStorageService on the same import line is still used and stays.

// --- paths --- went with CreatePluginPathsArgs: it was that section's only member.

src/core/types.d.ts

Declarationgrep -rnw result
ResolveDependenciesOptionssrc/core/types.d.ts:92:export interface ResolveDependenciesOptions { (1 hit)
ManifestLoadResultsrc/core/types.d.ts:115:export type ManifestLoadResult = LoadedManifest | FailedManifest (1 hit)

ManifestLoadResult is an alias whose two members are live and stay: src/core/manifest.js:24
writes @returns {Promise<LoadedManifest|FailedManifest>} directly rather than
naming the alias, and LoadedManifest is imported by src/core/cli/dispatch.js,
src/core/plugin_catalog.js, and src/core/runtime/types.d.ts.

CapabilityRegistryHandle (the only member of ResolveDependenciesOptions) stays -
still used by DepGraphResolution in the same file, so no import was stranded here.

src/core/cli/types.d.ts

Declarationgrep -rnw result
WalkthroughResultsrc/core/cli/types.d.ts:89:export interface WalkthroughResult { (1 hit)

git log --oneline -S'WalkthroughResult' names e902f6e as the last touch: "CLI
cleanup: split core_commands, unify argv parsing, delete the dead walkthrough (#241)"
.
The walkthrough went; its result shape did not. The similarly-named
PickerWalkthroughResult (same file, line 245) is live and untouched.

HypAwareV2Config (referenced by the removed interface) is still used elsewhere in
the file, so no import was stranded.


Deliberately left behind

These looked dead by the same one-occurrence scan and were kept. This is the part
worth reviewing - each is a case where the mechanical signal was wrong.

DeclarationWhy it stays
IngestSignal, IdentityResponse, IdentityBootstrapRequest (hypaware-core/plugins-workspace/central/src/types.d.ts)The file header states these are the wire contract with a separate repo: "Wire types for @hypaware/central@hypaware/server. The server package (post-V1 Phase 10, separate repo) will import from this same file; updates here must keep both ends in sync." An in-repo search can never see the other end.
PluginModule, CollectivusV2Config (hypaware-plugin-kernel-types.d.ts)That file is the published plugin kernel contract - listed in package.jsonfiles, and named by src/core/index.d.ts as "the canonical source of truth for the design types". PluginModule is the shape a third-party plugin's entry module must export; nothing in-repo names it precisely because the implementers are out of repo. Off-limits.
ObservabilityHandle (src/core/observability/types.d.ts)Its own comment says it exists for consumers of the generated declaration: "The precise return of installObservability ... is what consumers see via the generated index.d.ts. This named handle is the self-contained shape of that return."./core/observability is a public exports subpath.
LocalOnlyListFile (src/core/usage-policy/types.d.ts)Documents the v1 on-disk format that is still migrated on read (LLP 0071 / LLP 0103: "Superseded by LocalOnlyListFileV2 ... a bare dirs array migrates on read"). Deleting it would delete the description of a format the code still parses.
ParsedNeighbors (context-graph), CreateEmbedder (embedder-openai), ShardBuildReport (vector-search), GraphRowBuilders etc. (plugin types.d.ts files)Plugin-local declared contract shapes. After central/src/types.d.ts turned out to be a cross-repo contract, my confidence that an unreferenced plugin type is dead rather than declared is not high enough to act on. Left alone.

Also examined and not touched:

  • firstPartyPluginMetadata (src/core/config/validate.js). Carries an
    @deprecated Prefer buildPluginCatalog() tag, which reads as a cleanup target. It
    is not: it is re-exported from src/core/index.js (the . and ./core package
    entry), referenced by src/core/index.d.ts, used as the default knownPlugins at
    four sites inside validate.js, and asserted by three test files. Live public API.
  • Every "unused export" from step 2 (69 names, e.g. OAUTH_TOKEN_URL, buildUnit,
    cronMatches, runVerbCommand, planDaemonInstall). All are read inside their own
    module. Their export keyword may be unnecessary, but the values are not dead and
    narrowing a module's surface is a refactor, not autophagy.
  • Unused function parameters (~31 TS6133 hits). Changing a signature is a
    refactor with call-site arity implications. Out of scope.
  • types/, node_modules/, notes-archive/. Generated, vendored, archived.
    Excluded from every search and untouched.

Checks

Run in a detached worktree off origin/master.

npm run typecheck - clean, exit 0.

> tsc -p tsconfig.json --noEmit

npm test - identical to baseline.

baseline (origin/master, pristine)this branch
tests30143014
pass30053005
fail88
skipped11

The 8 failures are pre-existing on origin/master and unrelated to this change.
Confirmed by name against a pristine origin/master checkout before any edit; the
identical set fails after:

not ok 890 - leave after join removes the seed and reports the server
not ok 891 - leave clears an applied central slot, not just the seed
not ok 892 - leave reverses org-driven attaches and drops the forward identity
not ok 894 - leave after join also warns about a local central sink that keeps forwarding
not ok 895 - leave is idempotent: a second leave is the not-connected no-op
not ok 896 - leave still tears down when only a stale attach marker survives a prior partial leave
not ok 897 - leave removes the assets its attach marker records, and leaves manual copies alone
not ok 898 - leave self-heals an org attach whose plugin is gone: drops the marker, warns, stays clean

All eight are in test/core/leave-command.test.js. Nothing else regressed.

Ref hygiene (test/core/llp-ref-hygiene.test.js, inside npm test) - passes. No
@ref annotation was in or adjacent to any removed block:

ok 901 - every @ref resolves to a live LLP document and one of its anchors
ok 903 - no @ref annotation separates its gloss with an em dash

npm run smoke -- core_boot_noop - ok. The runtime type module is on the kernel
boot path, so this exercises it end-to-end even though the change is type-only.


Confidence

Reachability here is by static search, and static search cannot see two things that
this repo genuinely has: consumers outside the repo, and string-keyed dispatch. I
kept everything that showed either signal. What is left is eight declarations whose
names appear exactly once in the tree, in files with no public exports subpath and
no star re-export (grep -rn "export \*" --include=*.d.ts over src, bin,
hypaware-core, hypaware-plugin-kernel-types.d.ts returns only
src/core/index.d.ts:9: export * from './observability/index.js', which does not
re-export any types.d.ts).

A reviewer who disagrees about any single row should drop that row rather than the
PR; the removals are independent.

Type-only trim. Each removed declaration had exactly one occurrence in
the tree (its own definition): no importer, no `@import`, no test
reference, no `@ref` annotation, and no re-export from any public entry.
- `src/core/runtime/types.d.ts`: `CreateKernelRuntimeArgs`,
`CreateActivationContextArgs`, `CreatePluginPathsArgs`,
`ActivatePluginsArgs`, `ActivatePluginsResult`. Leftovers from the
paired-.d.ts consolidation (#182/#183); `activation.js` and `paths.js`
spell these param shapes inline in JSDoc instead.
- `src/core/types.d.ts`: `ResolveDependenciesOptions`,
`ManifestLoadResult`. `manifest.js` writes
`Promise<LoadedManifest|FailedManifest>` directly; both members stay.
- `src/core/cli/types.d.ts`: `WalkthroughResult`, orphaned by "delete the
dead walkthrough" (#241).
Removing those left `PluginPaths` and `SourceWithholdResolver` as unused
type imports in `src/core/runtime/types.d.ts`; dropped both.
No runtime code changed. npm test: 3005 pass / 8 fail / 1 skipped, the
same eight `leave-command.test.js` failures present on origin/master.
npm run typecheck clean. `npm run smoke -- core_boot_noop` ok.
Co-Authored-By: Claude <noreply@anthropic.com>
@philcunliffe

Copy link
Copy Markdown
ContributorAuthor

Neutral review - round 1/2 - 2e52ac5

Verdict: clean. No actionable findings. Nothing was pushed; the head is unchanged.

I did not take the PR body's reachability table on trust. Every claim below marked
executed was re-derived from scratch in my own detached worktrees (one at the PR head,
one at pristine origin/master14e2d96). The main checkout was never written to.


1. Reachability, re-run independently (executed)

For all eight names, run from the repo root at origin/master (the tree where the
declarations still exist):

CreateKernelRuntimeArgs -> src/core/runtime/types.d.ts:164 (1 hit)
CreateActivationContextArgs -> src/core/runtime/types.d.ts:179 (1 hit)
CreatePluginPathsArgs -> src/core/runtime/types.d.ts:189 (1 hit)
ActivatePluginsArgs -> src/core/runtime/types.d.ts:219 (1 hit)
ActivatePluginsResult -> src/core/runtime/types.d.ts:227 (1 hit)
ResolveDependenciesOptions -> src/core/types.d.ts:92 (1 hit)
ManifestLoadResult -> src/core/types.d.ts:115 (1 hit)
WalkthroughResult -> src/core/cli/types.d.ts:89 (1 hit)

Confirmed: exactly one hit each, the declaration itself.

On the exclusions. I re-ran every search a second time with onlynode_modules and
.git excluded - dropping the types and notes-archive exclusions the PR body used.
The counts were identical (1 hit each), so those two exclusions were not hiding a live
reference. Independently:

  • types/ is not tracked (git ls-files types -> 0 files) and is .gitignored with
    the comment "Generated declaration output (built by npm run build:types) ... never
    committed"
    . It is regenerated from src/, so excluding it is correct. Verified below
    by actually generating it.
  • notes-archive/ is genuinely an archive: two files, both LLP review markdown
    (notes-archive/llp-reviews/*.md). Neither mentions any removed name.

2. Published surface (executed - this is the check that mattered)

A green typecheck does not prove a .d.ts declaration is dead, so I built the real
thing. npm run build:types on origin/master (exit 0) emits 176 .d.ts files into
types/. Grepping that generated tree for all eight names returns zero hits for every
one
.

That is the decisive result, because the generated tree is what exports actually serves,
and it reaches back into src/**/types.d.ts by root-anchored specifier - e.g.
types/core/dep_graph.d.ts:27: import type { DepGraphResolution } from '../../src/core/types.js'.
So a declaration in a touched file can be published. None of the removed eight is.
Corroboration in the same tree: types/core/cli/walkthrough.d.ts:269 imports
PickerWalkthroughResult, the live near-namesake, which is untouched - the grep -w in
the PR body was load-bearing and it held.

Surface audit, all four routes:

  • exports - eight subpaths. . / ./core -> src/core/index.d.ts, which
    re-exports nothing from the three touched files (I read it in full). ./integration ->
    src/core/cli/integration.d.ts, which re-exports only ClientResult,
    IntegrationOptions, IntegrationCommandResult. The other five point into generated
    types/, cleared above. With an exports map present, deep paths like
    hypaware/src/core/runtime/types.d.ts are not importable even though files
    ships src/.
  • files / bin - bin/hypaware.js is runtime only; no removed name appears
    anywhere under bin/.
  • hypaware-plugin-kernel-types.d.ts - contains none of the eight.
  • Star re-exports - repo-wide, the only ones are
    src/core/index.js:8 and src/core/index.d.ts:9, both export * from './observability/index.js'.
    Neither re-exports a types.d.ts. Declaration merging is also ruled out: a name with
    exactly one occurrence tree-wide cannot be merged into from elsewhere.

Kept-list spot-check, both directions. The stricter direction (wrongly removed) is
settled above. In the other direction I confirmed each kept name is kept for a real reason,
not padding: PluginModule + CollectivusV2Config live in the published kernel contract
hypaware-plugin-kernel-types.d.ts; ObservabilityHandle's own header
(src/core/observability/types.d.ts:1-5) says it exists precisely so ./core/observability
consumers see the shape via the generated index.d.ts; LocalOnlyListFile documents a v1
on-disk format still migrated on read. The line is drawn in the right place.

3. Cross-repo wire contracts (executed)

I searched every.d.ts in the repo for cross-repo markers
(@hypaware/central|@hypaware/server|separate repo|cross-repo|wire contract|wire types|both ends|in sync).
Exactly two files carry one: hypaware-core/plugins-workspace/central/src/types.d.ts:1-3
and hypaware-plugin-kernel-types.d.ts. Neither is touched by this PR. The three
touched files carry no such marker - I read all three headers. Nothing comparable was
missed.

4. Correctness of the two import removals (executed)

After the removals, PluginPaths and SourceWithholdResolver have zero occurrences
remaining in src/core/runtime/types.d.ts - correctly stranded, correctly dropped.
ExtendedQueryStorageService on the same line is still used and correctly retained (it is
the sole + line in the whole diff). I also swept every remaining import in that file:
no import was left unused, and none was over-removed. Both dropped names remain
heavily used elsewhere, e.g. src/core/runtime/activation.js:23.

Reasoned (not executed): the five runtime interfaces really are paired-.d.ts residue -
activation.js:55 / :126, paths.js:43 and loader.js:47 all destructure their
parameters inline and their @import blocks name only KernelRuntime,
ActivationResult, PluginActivationEntry. The cascade check holds:
ActivationSuccess/ActivationFailure survive via the live ActivationResult union.

5. House rules (executed)

  • No em dash introduced. The diff adds zero U+2014. Three pre-existing em dashes remain
    in src/core/runtime/types.d.ts (lines 80, 90, 101 on master) - they are untouched by
    this PR and are part of a wider pre-existing pattern (29 files under src/). Out of
    scope here; flagging only so it is not mistaken for regression.
  • No semicolons introduced (the one ; hit is mid-sentence prose in a comment).
  • No @typedef, no inline import('...') types, no TypeScript-outside-JSDoc.
  • No @ref LLP annotation was in or adjacent to any removed block - the three touched
    files contain zero@ref annotations at all (grep -n "@ref" -> empty).
  • Diff scope confirmed: one commit, 3 files, +1/-64, .d.ts only, no runtime code.

6. Checks (executed, in my own worktrees)

CheckResult
npm run typecheck @ headexit 0, clean
npm run build:types @ masterexit 0, 176 .d.ts emitted
npm test @ head3014 tests, 3005 pass / 8 fail / 1 skipped
npm test @ pristine origin/master3014 tests, 3005 pass / 8 fail / 1 skipped

The two failure sets are identical name-for-name (diff of the sorted not ok names
-> no difference). All eight are the test/core/leave-command.test.jsleave * cases, and
they fail the same way on pristine origin/master, so they are pre-existing and not
attributable to this PR
- confirmed against the baseline as instructed, not inferred.
Ref hygiene passes at head: ok 901 - every @ref resolves to a live LLP document and one of its anchors, ok 903 - no @ref annotation separates its gloss with an em dash. CI is green
at this head and remains the authority; the above is corroboration.

Note on tooling

The code-review skill is not installed on this host (available project skills are
llp-* and ref-* only). Rather than invoke a substitute whose first step is a
gh pr checkout in the read-only main checkout, I performed the audit directly with the
targeted checks above, which are narrower and stronger for a deletion PR than a generic
diff review would have been.

Bottom line

The only high-severity outcome available here - "this removed something actually
reachable" - did not occur. All eight declarations are unreferenced in source, absent
from the generated declaration tree, unreachable through any exports subpath, and carry
no cross-repo contract marker. The two import removals are exactly the stranded pair.
Nothing to fix, so nothing was pushed and the head is unchanged at 2e52ac5.

Reviewed by neutral (LLP 0028/0029). Draft status and merge remain a human's call.

@philcunliffephilcunliffe added the neutral:approved neutral reviewed this and holds it for a maintainer merge (own or adopted PR; LLP 0025/0030) label Jul 30, 2026
@philcunliffe
philcunliffe marked this pull request as ready for review July 30, 2026 20:11
@philcunliffe
philcunliffe merged commit a1de85b into masterJul 30, 2026
9 checks passed
@philcunliffe
philcunliffe deleted the autophagy/cleanup-2026-07-30 branch July 30, 2026 21:31
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

neutral:approvedneutral reviewed this and holds it for a maintainer merge (own or adopted PR; LLP 0025/0030)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@philcunliffe