@ankhorage/devtools 1.19.18 → 1.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  # @ankhorage/devtools
5
5
 
6
- ![license: MIT](././paradox/badges/license.svg) ![npm: v1.19.18](././paradox/badges/npm.svg) ![runtime: bun](././paradox/badges/runtime.svg) ![typescript: strict](././paradox/badges/typescript.svg) ![eslint: checked](././paradox/badges/eslint.svg) ![prettier: checked](././paradox/badges/prettier.svg) ![build: checked](././paradox/badges/build.svg) ![tests: checked](././paradox/badges/tests.svg) ![docs: paradox](././paradox/badges/docs.svg)
6
+ ![license: MIT](././paradox/badges/license.svg) ![npm: v1.20.0](././paradox/badges/npm.svg) ![runtime: bun](././paradox/badges/runtime.svg) ![typescript: strict](././paradox/badges/typescript.svg) ![eslint: checked](././paradox/badges/eslint.svg) ![prettier: checked](././paradox/badges/prettier.svg) ![build: checked](././paradox/badges/build.svg) ![tests: checked](././paradox/badges/tests.svg) ![docs: paradox](././paradox/badges/docs.svg)
7
7
 
8
8
  Shared tooling, repository automation, runtime policies, and agent standards for Ankhorage TypeScript projects
9
9
 
@@ -36,71 +36,57 @@ repository root. Do not resolve it relative to this skill's own installation loc
36
36
 
37
37
  1. `<repo-root>/.agents/skills/hexagonal-architecture/SKILL.md`
38
38
 
39
- ## Required source layout
40
-
41
- - `examples/`: Repository-root folder in this standalone repository;
42
- Use it for complete, intentional, user-facing examples that people can inspect, copy, install, and run independently of a monorepo or internal fixture layout.
43
-
44
- Each example lives in a named subdirectory, such as `examples/basic-usage/*.ts`. Do not put example
45
- source files directly under `examples/`.
46
-
47
- Test-only fixtures remain owned by the applicable test structure. Do not relabel fixtures as public
48
- examples merely to bypass repository structure rules.
49
-
50
- - `src/cli/` must exist or have a concrete issue tracking the missing CLI commands;
51
- CLI modules are thin inbound adapters: they parse input, invoke a feature use case, and render
52
- output.
53
-
54
- The filesystem below `src/cli/commands/` mirrors the public command path after the package prefix:
55
-
56
- ```text
57
- ankh <package> <segment> ... <command>
58
- -> src/cli/commands/<segment>/.../<command>.ts
59
- ```
60
-
61
- The package prefix is represented by the provider and is not repeated under `commands/`. Flags and
62
- positional arguments do not affect this directory tree. Each command file follows the one-export
63
- rule: `commands/projects/list.ts` exports `list` and owns only the command-specific input/output
64
- mapping.
65
-
66
- - `src/features/`: Lists the repository's actual product capabilities;
67
- Technical categories are not features. Each feature owns its own hexagonal structure as needed,
68
- following the required Hexagonal Architecture skill. Do not create empty layers.
69
-
70
- ```text
71
- examples/
72
- <example>/
73
- src/
74
- cli/
75
- createCliProvider.ts
76
- commands/
77
- <command>.ts
78
- <group>/
79
- <command>.ts
80
- features/
81
- <feature>/
82
- domain/
83
- application/
84
- ports/
85
- inbound/
86
- outbound/
87
- use-cases/
88
- adapters/
89
- inbound/
90
- outbound/
91
- composition/
92
- constants/
93
- <topic>.ts
94
- utils/
95
- types/
96
- <topic>.ts
97
- constants/
98
- <topic>.ts
99
- utils/
100
- ```
101
-
102
- Keep only deliberate package facades directly under `src/`. Public package subpaths must name their
103
- explicit module in `package.json`; generic `index.ts` barrels are not public API exceptions.
39
+ ## Architecture profiles and source layout
40
+
41
+ Do not impose one folder tree on every repository. Select the smallest profile that matches the
42
+ repository's real responsibility, then enforce that profile's vocabulary and dependency direction.
43
+ Read `references/architecture-profiles.md` and `references/hexagonal-invariants.md` before
44
+ creating or moving architectural directories.
45
+
46
+ Valid profiles include:
47
+
48
+ - simple/value/contracts library;
49
+ - reusable UI or design-system library;
50
+ - application, engine, or hybrid package;
51
+ - provider or platform adapter package;
52
+ - tooling package;
53
+ - generated standalone application;
54
+ - an explicitly documented repository-specific profile such as Studio.
55
+
56
+ A package may start flat. Introduce `domain/`, `application/`, `ports/`, `adapters/`,
57
+ `composition/`, `features/`, or `core/` only when those names communicate a real architectural
58
+ role. Once a vocabulary is introduced, its combinations must be coherent:
59
+
60
+ - `domain/` may stand alone and must remain independent from outer mechanisms;
61
+ - `application/` coordinates use cases and may depend inward on domain policy and required ports;
62
+ - `ports/` define capabilities required by inner policy; they do not implement provider technology;
63
+ - `adapters/` translate or implement a port at an external edge and therefore require an inward
64
+ capability boundary to adapt to;
65
+ - `composition/` is outer wiring and exists only when concrete implementations need selection;
66
+ - `features/` is feature-first organization, not a generic bucket. Each feature owns a coherent
67
+ slice and may introduce only the role directories it actually needs;
68
+ - `core/` is allowed only when the repository defines it narrowly as stable inner policy. It must
69
+ never become a miscellaneous dumping ground.
70
+
71
+ Dependency direction is the invariant. Inner policy must not import outer mechanisms. A domain or
72
+ core module must not depend on application orchestration, adapters, composition, CLI, host,
73
+ platform, framework, database, or provider implementation details. Application/use-case code must
74
+ not import concrete adapters or composition roots. Adapters may depend inward on ports/application/
75
+ domain contracts. Composition may depend on all pieces it wires.
76
+
77
+ Do not create empty layers for symmetry. A small package with no domain orchestration does not need
78
+ hexagonal ceremony. UI libraries use component/foundation dependency direction rather than fake
79
+ application ports. Contracts libraries remain portable and side-effect free.
80
+
81
+ Repository-root `examples/` contains complete user-facing examples. Each example lives in a named
82
+ subdirectory. Test-only fixtures remain test-owned.
83
+
84
+ Package-level delivery edges such as `src/cli/`, `src/host/`, `src/app/`, or `src/platform/`
85
+ remain thin adapters/composition boundaries. The filesystem below `src/cli/commands/` mirrors the
86
+ public Ankh command path, and command modules parse input, invoke package behavior, and render output.
87
+
88
+ Keep only deliberate public facades directly under `src/`. Public package subpaths must map to
89
+ explicit package exports; generic barrels are not an excuse to bypass ownership.
104
90
 
105
91
  ## General Taxonomy
106
92
 
@@ -0,0 +1,141 @@
1
+ # Architecture Profiles
2
+
3
+ Choose the profile from actual ownership and consumers. Profiles define allowed vocabulary and
4
+ dependency direction; they are not templates that require every listed directory.
5
+
6
+ ## Simple, value, or contracts library
7
+
8
+ Use for portable types, deterministic values, parsers, constants, algorithms, and small libraries
9
+ without application orchestration.
10
+
11
+ Typical forms:
12
+
13
+ ```text
14
+ src/
15
+ index.ts
16
+ <domain-or-topic>/
17
+ types/
18
+ constants/
19
+ utils/
20
+ ```
21
+
22
+ Do not invent ports, adapters, application, or composition layers when there is no external edge to
23
+ abstract. Contracts packages additionally keep public declarations serializable and free of runtime
24
+ implementation.
25
+
26
+ ## Reusable UI or design-system library
27
+
28
+ Use semantic UI ownership and stable foundation layers rather than fake use cases:
29
+
30
+ ```text
31
+ src/
32
+ foundation/
33
+ theme/
34
+ layout/
35
+ primitives/
36
+ components/
37
+ patterns/
38
+ registry/
39
+ ```
40
+
41
+ Higher-level UI may depend on lower-level foundations; foundations must not depend upward on composed
42
+ components or registries. Provider execution belongs outside reusable presentation components.
43
+
44
+ ## Application, engine, or hybrid package
45
+
46
+ Use when the package owns use cases, state transitions, external systems, or several delivery edges.
47
+ Domain-first and feature-first organization are both valid when coherent.
48
+
49
+ Domain-first example:
50
+
51
+ ```text
52
+ src/
53
+ <domain>/
54
+ domain/
55
+ application/
56
+ ports/
57
+ adapters/
58
+ composition/
59
+ cli/
60
+ host/
61
+ app/
62
+ platform/
63
+ ```
64
+
65
+ Feature-first example:
66
+
67
+ ```text
68
+ src/
69
+ features/
70
+ <feature>/
71
+ domain/
72
+ application/
73
+ ports/
74
+ adapters/
75
+ composition/
76
+ cli/
77
+ ```
78
+
79
+ Only create the role directories that the capability actually needs. A pure domain feature can stop
80
+ at `domain/`; an in-memory use case need not invent an outbound adapter.
81
+
82
+ ## Provider or platform adapter package
83
+
84
+ Use when the package deliberately implements an external technology boundary:
85
+
86
+ ```text
87
+ src/
88
+ contracts/
89
+ planning/
90
+ adapters/
91
+ composition/
92
+ cli/
93
+ ```
94
+
95
+ Portable configuration and planning stay independent from SDK/runtime values. Concrete provider code
96
+ stays in adapters.
97
+
98
+ ## Tooling package
99
+
100
+ Command-centric tooling may use:
101
+
102
+ ```text
103
+ src/
104
+ cli/
105
+ policy/
106
+ application/
107
+ adapters/
108
+ composition/
109
+ ```
110
+
111
+ Policy remains deterministic. Filesystem, process, registry, network, and GitHub behavior stay at
112
+ the edge.
113
+
114
+ ## Generated standalone application
115
+
116
+ A generated app owns its manifest, lockfile, installation, validation, build, and deployment inputs.
117
+ A parent tool may invoke it with the app as `cwd`, but it must not depend on a hidden parent
118
+ workspace, sibling source, or installation state.
119
+
120
+ ## Repository-specific profile
121
+
122
+ A repository may define a narrower profile when its domain genuinely needs one. That profile must be
123
+ documented in the managed project-structure skill or an explicit repository reference and must still
124
+ respect the shared standalone and dependency-direction invariants. Studio is the canonical example:
125
+ its `features/` taxonomy is intentional and each substantial feature may layer internally.
126
+
127
+ ## Combination rules
128
+
129
+ Folder names create obligations:
130
+
131
+ - `domain/`: inner policy; no outward mechanism dependencies.
132
+ - `application/`: use-case orchestration; no concrete adapter/composition dependency.
133
+ - `ports/`: capability contracts required by inner policy.
134
+ - `adapters/`: concrete edge implementations; there must be an inward capability/policy to adapt.
135
+ - `composition/`: selects and wires concrete implementations; do not create it without pieces to wire.
136
+ - `features/`: siblings are product capabilities, not technical categories.
137
+ - `core/`: only a narrowly defined inner-policy layer; never a generic dumping ground.
138
+ - `common/`, `shared/`, and `helpers/`: not architectural ownership categories.
139
+
140
+ Doctor should validate these combinations and dependency directions rather than require every
141
+ repository to match one tree.
@@ -0,0 +1,80 @@
1
+ # Hexagonal Architecture Invariants
2
+
3
+ The canonical rule is isolation of inner policy from external mechanisms, not the visual shape or a
4
+ fixed number of directories.
5
+
6
+ ## Research basis
7
+
8
+ - Alistair Cockburn's original Ports & Adapters article defines an application on the inside
9
+ communicating through purposeful ports with replaceable technology-specific adapters. It
10
+ explicitly notes that the number of ports is not fixed:
11
+ https://alistair.cockburn.us/hexagonal-architecture
12
+ - Robert C. Martin's Clean Architecture states the Dependency Rule: source dependencies point
13
+ inward, while outer mechanisms must not leak names or formats into inner policy:
14
+ https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html
15
+ - Martin Fowler describes layering as a logical separation that can exist at different granularities
16
+ and notes that larger systems often modularize primarily by domain, layering inside those modules:
17
+ https://martinfowler.com/bliki/PresentationDomainDataLayering.html
18
+ - DDD-oriented layered architecture keeps domain rules independent from infrastructure while the
19
+ application layer coordinates use cases and infrastructure implements technical details:
20
+ https://learn.microsoft.com/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/ddd-oriented-microservice
21
+
22
+ ## Invariants
23
+
24
+ ```text
25
+ outer adapter/composition -> application/use case -> domain/core policy
26
+ |
27
+ v
28
+ required port contract
29
+
30
+ concrete adapter ----------------> required port contract
31
+ ```
32
+
33
+ The exact filesystem can vary, but source dependencies must preserve this direction.
34
+
35
+ ### Inner policy
36
+
37
+ Domain/core policy owns deterministic rules, values, invariants, and transformations. It must not
38
+ import:
39
+
40
+ - CLI, HTTP, UI, worker, or framework entrypoints;
41
+ - filesystem/process/network/database/provider SDK implementations;
42
+ - adapters or composition roots;
43
+ - application orchestration that sits outside that policy.
44
+
45
+ ### Application/use cases
46
+
47
+ Application code coordinates domain policy and required capabilities. It may define or consume port
48
+ contracts, but it must not import concrete adapter implementations or composition roots.
49
+
50
+ ### Ports
51
+
52
+ A port names a capability or conversation at a boundary. Create one when an external side effect,
53
+ provider, process, platform, storage mechanism, or multiple delivery mechanisms justify substitution
54
+ or deterministic testing. A port is not required for an ordinary pure function call.
55
+
56
+ ### Adapters
57
+
58
+ Adapters translate at the edge. Inbound adapters map CLI/HTTP/UI/worker input into an application
59
+ operation. Outbound adapters implement required capabilities using concrete technology.
60
+
61
+ An `adapters/` directory without any identifiable inward policy/capability boundary is structurally
62
+ suspicious: technology has become the architecture instead of adapting it.
63
+
64
+ ### Composition
65
+
66
+ Composition selects implementations and wires dependencies. It is intentionally outermost and may
67
+ know concrete adapters. Inner policy must never import it.
68
+
69
+ ## Verification strategy
70
+
71
+ Doctor should validate what can be proven statically:
72
+
73
+ - local dependency protocols and sibling-source coupling;
74
+ - folder-role combinations after a vocabulary is introduced;
75
+ - relative import direction between recognized roles;
76
+ - generic catch-all architecture directories;
77
+ - public-package standalone scripts and packed artifact boundaries.
78
+
79
+ Semantic independence that cannot be inferred statically belongs in the package-owned
80
+ `test:standalone` suite. Release must execute both Doctor and that owner test.
@@ -35,6 +35,15 @@ Dependency direction is always inward:
35
35
  - Domain -> domain-only abstractions (no framework or infrastructure dependencies)
36
36
  - Domain -> nothing external
37
37
 
38
+ ## Structural rule
39
+
40
+ Hexagonal architecture does not prescribe one mandatory directory tree or a fixed number of ports.
41
+ The enforceable contract is dependency direction and replaceability: inner policy must remain
42
+ independent from outer technology, and adapters translate external mechanisms at explicit
43
+ boundaries. Use the repository's managed `ankhorage-project-structure` skill to select a concrete
44
+ profile and validate folder-role combinations. Do not create empty layers or ports merely to match
45
+ a diagram.
46
+
38
47
  ## How It Works
39
48
 
40
49
  ### Step 1: Model a use case boundary
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ankhorage/devtools",
3
- "version": "1.19.18",
3
+ "version": "1.20.0",
4
4
  "description": "Shared tooling, repository automation, runtime policies, and agent standards for Ankhorage TypeScript projects",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/ankhorage/devtools#readme",
@@ -150,7 +150,7 @@
150
150
  "devDependencies": {
151
151
  "@ankhorage/paradox": "^0.1.26",
152
152
  "@ankhorage/ankh": "^0.10.4",
153
- "@ankhorage/doctor": "0.10.39",
153
+ "@ankhorage/doctor": "0.10.40",
154
154
  "@techstark/opencv-js": "^5.0.0-release.1",
155
155
  "@types/bun": "^1.4.1",
156
156
  "@types/node": "^26.6.2",