@ankhorage/devtools 1.11.7 → 1.11.9

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
@@ -194,10 +194,12 @@ Only the current Ankhorage architecture is supported. Managed instructions rejec
194
194
 
195
195
  ## Managed repository skills
196
196
 
197
- `ankh devtools skills sync` owns the complete `.agents/skills/ankhorage-coding-rules/` and `.agents/skills/ankhorage-project-structure/` trees from the immutable copies shipped in the Devtools release. It creates `.agents/` when missing, replaces stale files in those managed skills, and preserves every unrelated skill directory.
197
+ `ankh devtools skills sync` owns the complete `.agents/skills/ankhorage-coding-rules/`, `.agents/skills/hexagonal-architecture/`, and `.agents/skills/ankhorage-project-structure/` trees from the immutable copies shipped in the Devtools release. It creates `.agents/` when missing, replaces stale files in those managed skills, and preserves every unrelated skill directory. The project-structure skill requires both the coding-rules and hexagonal-architecture skills before structural work can continue.
198
198
 
199
199
  `.agents/.devtools-manifest.json` records the source Devtools version and SHA-256 hashes for every managed skill file. That ownership record allows status and dry-run to report drift and lets later releases remove stale owned files without deleting repository-owned skills.
200
200
 
201
+ Agent Skill scripts are always TypeScript files with a `.ts` extension and run with Bun. JavaScript skill scripts using `.js`, `.mjs`, or `.cjs` are not supported.
202
+
201
203
  ## ESLint profiles
202
204
 
203
205
  `createConfig()` defaults to `profile: 'auto'`.
@@ -18,6 +18,7 @@ const REQUIRED_README_SNIPPETS = [
18
18
  'devtools.agents.sync',
19
19
  'devtools.skills.sync',
20
20
  'ankhorage-coding-rules',
21
+ 'hexagonal-architecture',
21
22
  'devtools.prettier.sync',
22
23
  'devtools.knip.sync',
23
24
  'devtools.package.sync',
@@ -38,6 +38,12 @@ when they support states that the current architecture can intentionally produce
38
38
  For directory ownership, package boundaries, architectural profiles, ports and adapters, public
39
39
  entrypoints, or cross-repository structural work, load and follow
40
40
  \`.agents/skills/ankhorage-project-structure/SKILL.md\`.
41
+
42
+ ## Skill scripts
43
+
44
+ Scripts inside an Agent Skill must always be TypeScript files with the \`.ts\` extension.
45
+ JavaScript skill scripts using \`.js\`, \`.mjs\`, or \`.cjs\` are not allowed. Run TypeScript
46
+ skill scripts with Bun.
41
47
  `;
42
48
  }
43
49
  async function readPackageManifest(targetDirectory) {
@@ -47,9 +47,9 @@ exceptions or replaced by generic preferences from this skill.
47
47
 
48
48
  - Test observable behavior at the owning boundary. Keep tests deterministic and independent of
49
49
  execution order, ambient state, and live network services.
50
- - When testing dependency declarations, assert the required semver range shape or a shared policy
51
- value instead of a Renovate-managed literal version. Assert an exact version only when the pin is
52
- itself the contract under test.
50
+ - Do not hardcode package versions in tests. When testing dependency declarations, assert the
51
+ required semver range shape or a shared policy value instead of a Renovate-managed literal
52
+ version. Assert an exact version only when the pin is itself the contract under test.
53
53
  - Follow the range-shape patterns in the
54
54
  [Devtools repository sync test](https://github.com/ankhorage/devtools/blob/main/src/cli/runRepositoryCommand.test.ts)
55
55
  and [ZORA PR #313](https://github.com/ankhorage/zora/pull/313).
@@ -1,79 +1,121 @@
1
1
  ---
2
2
  name: ankhorage-project-structure
3
3
  description: >
4
- Design, review, or migrate the source structure of Ankhorage repositories and generated
5
- applications. Use for directory ownership, package boundaries, package CLI layout, repository
6
- skill distribution, public entrypoints, or cross-repository cleanup.
4
+ Define, review, or implement the standard source structure of Ankhorage repositories. Use for
5
+ feature ownership, CLI layout, hexagonal boundaries, source-module naming, utilities, or package
6
+ entrypoints.
7
7
  ---
8
8
 
9
9
  # Ankhorage Project Structure
10
10
 
11
- Apply the general ownership rules first. Only Studio currently has a mandated source taxonomy.
11
+ Every Ankhorage repository follows this structure. It applies now to `ankhorage/studio`,
12
+ `ankhorage/deploy`, `ankhorage/infra`, `ankhorage/repository`, and `ankhorage/navigator`.
13
+
14
+ ## Required skills
12
15
 
13
- Before deciding structure:
14
-
15
- 1. Read the repository `AGENTS.md`, `package.json`, exports, source tree, and representative tests.
16
- 2. Load `ankhorage-coding-rules` as the complementary implementation and testing authority.
17
- 3. Identify the repository's owning capability.
18
- 4. Identify current public subpaths and cross-package release boundaries.
19
-
20
- Repository-specific rules may refine this skill, but must not silently reverse package ownership
21
- or dependency direction.
22
-
23
- ## Primary boundary
24
-
25
- An Ankhorage repository/package is the primary bounded capability and independently released
26
- unit. Do not force a Studio directory tree onto libraries, providers, tooling, or generated
27
- applications.
28
-
29
- - Independently bindable capabilities belong in standalone packages.
30
- - Substantial responsibilities inside a package use cohesive directories owned by the package.
31
- - Cross-package access uses published APIs and declared dependencies, never sibling source.
32
- - A package owns its application behavior; adapters belonging to another package are not copied
33
- or proxied locally.
34
-
35
- When a package declares an Ankh provider or changes `src/cli/`, always read
36
- [cli.md](references/cli.md).
37
-
38
- When classifying a local or cross-repository utility, also read
39
- [utilities.md](references/utilities.md).
40
-
41
- When the task is a structural cleanup or migration, also read
42
- [migration.md](references/migration.md). For `ankhorage/studio`, always also read
43
- [studio.md](references/studio.md).
44
-
45
- When adding, distributing, or synchronizing repository-local agent skills, read
46
- [skill-distribution.md](references/skill-distribution.md).
47
-
48
- ## Universal invariants
49
-
50
- - Keep only intentional package entrypoints and required declaration shims directly under `src/`.
51
- - Keep one abstraction level and responsibility among siblings.
52
- - Prefer domain ownership over technical dumping grounds such as `common`, `core`, `helpers`,
53
- `misc`, or `shared`. `utils/` is the canonical local directory for genuine package-level
54
- utilities.
55
- - Colocate focused unit tests. Put cross-domain acceptance, E2E, smoke infrastructure, and large
56
- fixtures outside production source.
57
- - Public package subpaths may point to nested source. Do not keep files at `src/` merely because
58
- they are exported.
59
- - Preserve one canonical implementation. Do not add legacy paths, compatibility barrels, or
60
- duplicate APIs to make a migration appear smaller.
61
-
62
- ## Ownership decision
63
-
64
- For every file or new symbol, decide in order:
65
-
66
- 1. Which Ankhorage package owns the capability?
67
- 2. Which internal domain owns it?
68
- 3. Is it core policy, application orchestration, a required port, an edge adapter, composition,
69
- or a public entrypoint?
70
- 4. Is it reusable enough to belong in `@ankhorage/utility` instead?
71
-
72
- If any answer is unclear, resolve ownership before moving or creating code.
73
-
74
- ## Studio enforcement
75
-
76
- Only `ankhorage/studio` has a mandatory source taxonomy and hexagonal feature architecture. Its
77
- complete allowlist, exceptions, port/adapter rules, and generated-app policy are in
78
- [studio.md](references/studio.md). Other repositories remain structurally unconstrained beyond the
79
- universal invariants until their owning repository is deliberately brought into scope.
16
+ Before structural work, read the repository `AGENTS.md`, inspect its source tree and public
17
+ exports, then load both required repository skills:
18
+
19
+ 1. `.agents/skills/ankhorage-coding-rules/SKILL.md`
20
+ 2. [Hexagonal Architecture](../hexagonal-architecture/SKILL.md)
21
+
22
+ If `ankhorage-coding-rules` is missing or unreadable, stop immediately and report exactly:
23
+
24
+ ```
25
+ Cannot continue: the required repository skill `ankhorage-coding-rules` is missing or unreadable at `.agents/skills/ankhorage-coding-rules/SKILL.md`. Synchronize the repository skills from `@ankhorage/devtools` and retry.
26
+ ```
27
+
28
+ If `hexagonal-architecture` is missing or unreadable, stop immediately and report exactly:
29
+
30
+ ```
31
+ Cannot continue: the required repository skill `hexagonal-architecture` is missing or unreadable at `.agents/skills/hexagonal-architecture/SKILL.md`. Synchronize the repository skills from `@ankhorage/devtools` and retry.
32
+ ```
33
+
34
+ ## Required source layout
35
+
36
+ Every repository provides `src/features/`. It lists the repository's actual product capabilities;
37
+ technical categories are not features. Each feature owns its own hexagonal structure as needed,
38
+ following the required Hexagonal Architecture skill. Do not create empty layers.
39
+
40
+ Every repository provides `src/cli/`, or has a concrete issue tracking the missing CLI commands.
41
+ CLI modules are thin inbound adapters: they parse input, invoke a feature use case, and render
42
+ output.
43
+
44
+ ```text
45
+ src/
46
+ cli/
47
+ createCliProvider.ts
48
+ commands/
49
+ <command>.ts
50
+ <group>/
51
+ <command>.ts
52
+ features/
53
+ <feature>/
54
+ domain/
55
+ application/
56
+ ports/
57
+ inbound/
58
+ outbound/
59
+ use-cases/
60
+ adapters/
61
+ inbound/
62
+ outbound/
63
+ composition/
64
+ utils/
65
+ utils/
66
+ ```
67
+
68
+ Keep only deliberate package facades directly under `src/`. Public package subpaths must name their
69
+ explicit module in `package.json`; generic `index.ts` barrels are not public API exceptions.
70
+
71
+ The filesystem below `src/cli/commands/` mirrors the public command path after the package prefix:
72
+
73
+ ```text
74
+ ankh <package> <segment> ... <command>
75
+ -> src/cli/commands/<segment>/.../<command>.ts
76
+ ```
77
+
78
+ The package prefix is represented by the provider and is not repeated under `commands/`. Flags and
79
+ positional arguments do not affect this directory tree. Each command file follows the one-export
80
+ rule: `commands/projects/list.ts` exports `list` and owns only the command-specific input/output
81
+ mapping.
82
+
83
+ ## Feature taxonomy
84
+
85
+ Siblings always represent the same kind of entity. A folder cannot be an unrelated catch-all beside
86
+ peer entities. For example, this is invalid because `otherFolder` is not a color:
87
+
88
+ ```text
89
+ colors/
90
+ red/
91
+ green/
92
+ blue/
93
+ otherFolder/
94
+ ```
95
+
96
+ Resolve the ownership of `otherFolder` and move it to the appropriate taxonomy. Use domain names for
97
+ features, not framework, transport, database, or generic technical names.
98
+
99
+ ## One export per production module
100
+
101
+ Each production source file has exactly one export. Its exported declaration is the first declaration
102
+ after imports and module documentation, and its name matches the filename exactly.
103
+
104
+ - `myFunction.ts` exports `myFunction`.
105
+ - `myFunctionAsync.ts` exports `myFunctionAsync`.
106
+ - A public operation that is asynchronous or returns a `Promise` uses the `Async` suffix in both its
107
+ filename and exported name.
108
+
109
+ Keep private helpers below that exported declaration when they are used only by that module. Move a
110
+ helper used by multiple modules to `utils/` at the owning layer. Put a repository-wide utility in
111
+ `src/utils/`. Put a generally reusable cross-package utility in the correct `@ankhorage/utility`
112
+ location.
113
+
114
+ ## Utilities
115
+
116
+ `utils/` is the only utility directory name. Do not create `shared/`, `helper/`, `helpers/`,
117
+ `common/`, or equivalent catch-all folders. Feature-local utilities live in that feature's `utils/`;
118
+ utilities shared by repository features live in `src/utils/`.
119
+
120
+ This skill defines the target architecture. Schedule repository migrations separately and in this
121
+ order: Studio, Deploy, Infra, Repository, Navigator.
@@ -0,0 +1,72 @@
1
+ ---
2
+ name: hexagonal-architecture
3
+ description: >
4
+ Organize Ankhorage features with ports and adapters so domain policy stays independent from
5
+ transport, frameworks, and infrastructure.
6
+ origin: ECC, adapted for Ankhorage
7
+ metadata:
8
+ github-repo: https://github.com/affaan-m/ECC
9
+ github-ref: refs/tags/v2.2.0
10
+ github-path: docs/ja-JP/skills/hexagonal-architecture
11
+ ---
12
+
13
+ # Hexagonal Architecture
14
+
15
+ Hexagonal architecture keeps a feature's domain policy independent from its transport, framework,
16
+ and infrastructure details. The application layer depends on ports; inbound and outbound adapters
17
+ implement the edge-specific work.
18
+
19
+ ## Feature boundaries
20
+
21
+ Apply this structure inside the owning `src/features/<feature>/` directory. A feature may contain
22
+ only the layers it needs:
23
+
24
+ ```text
25
+ <feature>/
26
+ domain/
27
+ application/
28
+ ports/
29
+ inbound/
30
+ outbound/
31
+ use-cases/
32
+ adapters/
33
+ inbound/
34
+ outbound/
35
+ composition/
36
+ utils/
37
+ ```
38
+
39
+ - `domain/` contains entities, value objects, and business policy. It imports no framework,
40
+ transport, database, or SDK code.
41
+ - `application/` defines use cases and the ports they require. It orchestrates domain behavior and
42
+ depends only inward.
43
+ - `adapters/inbound/` converts CLI, HTTP, worker, or UI input to use-case input.
44
+ - `adapters/outbound/` implements application ports for persistence, APIs, queues, clocks, and
45
+ other external dependencies.
46
+ - `composition/` explicitly wires concrete adapters to use cases.
47
+
48
+ Dependency direction is always inward: adapters depend on application and domain; application
49
+ depends on domain and ports; domain has no external dependencies. Adapters do not call each other
50
+ to bypass a use case.
51
+
52
+ ## Ports and use cases
53
+
54
+ Define an inbound port when a feature needs a stable use-case boundary. Define an outbound port for
55
+ each capability the application needs from persistence, an external system, or cross-cutting runtime
56
+ services. Model ports as capabilities rather than technologies.
57
+
58
+ Use cases accept plain inputs, enforce application invariants, coordinate domain behavior through
59
+ ports, and return plain outputs. Keep protocol request objects, database rows, SDK clients, and
60
+ transport error formats in adapters.
61
+
62
+ ## Testing
63
+
64
+ Test domain rules without framework setup. Test use cases with fakes for outbound ports. Test
65
+ adapters at their boundary with the real protocol or infrastructure they translate. Cover critical
66
+ flows end-to-end through an inbound adapter, use case, and outbound adapter.
67
+
68
+ ## Ankhorage conventions
69
+
70
+ Follow `ankhorage-project-structure` for feature naming, one-export source modules, and `utils/`
71
+ ownership. Do not introduce legacy paths, compatibility facades, dual implementations, or rollback
72
+ switches while applying this architecture; use the current architecture directly.
@@ -0,0 +1,7 @@
1
+ interface:
2
+ display_name: 'Hexagonal Architecture'
3
+ short_description: 'Organize Ankhorage features with ports and adapters'
4
+ default_prompt: 'Use $hexagonal-architecture to design or review the feature boundaries for this Ankhorage change.'
5
+
6
+ policy:
7
+ allow_implicit_invocation: true
@@ -1,4 +1,4 @@
1
- export declare const BASELINE_SKILL_NAMES: readonly ["ankhorage-coding-rules", "ankhorage-project-structure"];
1
+ export declare const BASELINE_SKILL_NAMES: readonly ["ankhorage-coding-rules", "hexagonal-architecture", "ankhorage-project-structure"];
2
2
  export declare const PROFILE_SKILL_NAMES: readonly ["zora-designer"];
3
3
  export type ManagedSkillName = (typeof BASELINE_SKILL_NAMES)[number] | (typeof PROFILE_SKILL_NAMES)[number];
4
4
  /*** Select baseline and profile-specific managed skills from current repository traits. */
@@ -2,6 +2,7 @@ import { readFile } from 'node:fs/promises';
2
2
  import { resolve } from 'node:path';
3
3
  export const BASELINE_SKILL_NAMES = [
4
4
  'ankhorage-coding-rules',
5
+ 'hexagonal-architecture',
5
6
  'ankhorage-project-structure',
6
7
  ];
7
8
  export const PROFILE_SKILL_NAMES = ['zora-designer'];
@@ -22,10 +22,10 @@ permissions:
22
22
  jobs:
23
23
  changeset:
24
24
  if: >-
25
- (github.actor == 'renovate[bot]' || github.actor == 'ankhorage-renovate-sync[bot]') &&
25
+ (github.event.pull_request.user.login == 'renovate[bot]' || github.event.pull_request.user.login == 'ankhorage-renovate-sync[bot]') &&
26
26
  github.event.pull_request.head.repo.full_name == github.repository &&
27
27
  startsWith(github.event.pull_request.head.ref, 'renovate/')
28
- uses: ankhorage/renovate/.github/workflows/changeset.yml@03f29fb8f81d15c51bf16b5374ad92fe8f95e3b5
28
+ uses: ankhorage/renovate/.github/workflows/changeset.yml@858eb04e4c97798bf3be40fe7b4909d837294a01
29
29
  with:
30
30
  renovate_sync_client_id: ${{ vars.ANKHORAGE_RENOVATE_SYNC_CLIENT_ID }}
31
31
  secrets:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ankhorage/devtools",
3
- "version": "1.11.7",
3
+ "version": "1.11.9",
4
4
  "description": "Shared development tools and repository standards for Ankhorage",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/ankhorage/devtools#readme",
@@ -1,117 +0,0 @@
1
- # Ankhorage Package CLI
2
-
3
- An Ankhorage package may expose one package-level Ankh command provider under `src/cli/`. The
4
- package is the CLI ownership boundary.
5
-
6
- Do not create `cli/` directories inside internal domains. An independently bound package owns its
7
- own package-level `src/cli/` and release lifecycle.
8
-
9
- ## Command tree
10
-
11
- The filesystem below `src/cli/commands/` mirrors the public command path after the package prefix.
12
-
13
- ```text
14
- ankh <package> <segment> ... <command>
15
- -> src/cli/commands/<segment>/.../<command>.ts
16
- ```
17
-
18
- Examples:
19
-
20
- ```text
21
- ankh studio dev
22
- -> src/cli/commands/dev.ts
23
-
24
- ankh studio projects list
25
- -> src/cli/commands/projects/list.ts
26
-
27
- ankh studio projects create --name Shop
28
- -> src/cli/commands/projects/create.ts
29
-
30
- ankh deploy release inspect
31
- -> src/cli/commands/release/inspect.ts
32
- ```
33
-
34
- The package prefix is represented by the provider and is not repeated under `commands/`. Flags and
35
- positional arguments do not affect the directory tree.
36
-
37
- Bad:
38
-
39
- ```text
40
- src/cli/commands/studio/projects/list.ts
41
- src/cli/commands/listProjects.ts
42
- src/projects/cli/list.ts
43
- ```
44
-
45
- Good:
46
-
47
- ```text
48
- src/cli/commands/projects/list.ts
49
- ```
50
-
51
- ## Layout
52
-
53
- ```text
54
- src/
55
- cli/
56
- index.ts
57
- commands/
58
- <command>.ts
59
- <group>/
60
- <command>.ts
61
- ```
62
-
63
- `src/cli/index.ts` owns provider identity, category, capabilities, command definitions, handler
64
- registration, and package-level composition. It contains no substantial command implementation.
65
-
66
- Each leaf command module owns one command handler and its command-specific argument/output mapping.
67
- Tests are colocated:
68
-
69
- ```text
70
- src/cli/commands/projects/list.ts
71
- src/cli/commands/projects/list.test.ts
72
- ```
73
-
74
- Do not add command-group barrels unless the group intentionally exposes an API or requires genuine
75
- composition.
76
-
77
- ## Naming exception
78
-
79
- Command filenames follow public CLI segments rather than exported handler names:
80
-
81
- ```text
82
- command: ankh studio projects list
83
- file: src/cli/commands/projects/list.ts
84
- handler: listProjects
85
- ```
86
-
87
- This is an intentional exception to primary-symbol filenames. It applies only to CLI command leaf
88
- modules.
89
-
90
- ## Adapter boundary
91
-
92
- A handler may parse `request.argv`, use the provided command context, call package-owned
93
- application operations, translate failures into command results, and create the package
94
- composition needed for the invocation.
95
-
96
- A handler must not:
97
-
98
- - implement domain rules;
99
- - duplicate application behavior;
100
- - implement substantial filesystem, network, process, database, credential, or provider logic;
101
- - proxy behavior owned by another package to place it under the local prefix;
102
- - preserve removed commands through aliases or hidden handlers.
103
-
104
- ## Capabilities and public metadata
105
-
106
- Keep provider metadata, command definitions, handler paths, public exports, documentation, and
107
- tests synchronized. Remove unused capabilities when a command disappears. Published command or
108
- metadata changes require the repository's normal changeset treatment.
109
-
110
- ## Standalone generated applications
111
-
112
- Generated applications own their installation, validation, build, and runtime commands. Execute
113
- the generated application's canonical command with that application as `cwd`.
114
-
115
- Studio must not own a parallel workspace-install command or assume generated applications are
116
- Studio workspace members. Do not preserve obsolete workspace commands, capabilities, handlers,
117
- tests, or documentation after the standalone architecture replaces them.
@@ -1,61 +0,0 @@
1
- # Structural Migration
2
-
3
- Use this reference when the user requests repository cleanup, file movement, boundary correction,
4
- or adoption of the project structure.
5
-
6
- ## Establish the target first
7
-
8
- Before moving code:
9
-
10
- 1. inventory direct `src/` files, current domains, entrypoints, tests, and generated sources;
11
- 2. inventory package exports and consumers of public subpaths;
12
- 3. classify the repository profile;
13
- 4. identify code that belongs in another package;
14
- 5. define the intended final directory tree and dependency direction;
15
- 6. identify Utility additions and release gates;
16
- 7. identify obsolete behavior that should be deleted rather than relocated.
17
-
18
- Do not begin with a mechanical folder move while ownership remains unresolved.
19
-
20
- ## Migration units
21
-
22
- Migrate cohesive domains or vertical capabilities, not arbitrary batches of similarly named files.
23
- For each unit:
24
-
25
- 1. extract any required cross-repository utility first;
26
- 2. release the owning package before updating consumers;
27
- 3. move domain/application code and tests together;
28
- 4. move concrete edge behavior to its package-level adapter area;
29
- 5. preserve intentional public package subpaths by remapping exports to nested output;
30
- 6. remove obsolete barrels, aliases, and duplicate paths;
31
- 7. validate the focused unit before the full repository gates.
32
-
33
- Avoid a single repository-wide move when smaller coherent migrations give clearer review and
34
- rollback boundaries. Avoid tiny PRs that leave two competing architectures active for long periods.
35
-
36
- ## Root source policy
37
-
38
- At the target state, direct `src/` files are limited to intentional entrypoints such as `index.ts`,
39
- `root.ts`, required environment declarations, or other explicitly documented build entrypoints.
40
- Public export status alone does not justify root placement.
41
-
42
- ## Acceptance and enforcement
43
-
44
- After the structure is proven in a representative repository:
45
-
46
- - distribute the canonical structure skills through `ankh devtools sync` into
47
- `.agents/skills/<skill-name>/` as described in
48
- [skill-distribution.md](skill-distribution.md);
49
- - add Devtools import-boundary rules where static enforcement is reliable;
50
- - add Doctor profile checks for allowed root files and required package entrypoints;
51
- - use Knip to verify public exports and dead compatibility barrels;
52
- - keep repository `AGENTS.md` focused on repository-specific ownership rather than duplicating this
53
- skill.
54
-
55
- Enforcement belongs to Devtools and Doctor, not prose-only repository exceptions.
56
-
57
- ## No behavior drift
58
-
59
- A structural migration preserves current valid behavior unless deletion is an explicit part of the
60
- approved target architecture. Do not add compatibility implementations solely because files move.
61
- Use characterization or focused public-surface tests when a move crosses a meaningful boundary.
@@ -1,120 +0,0 @@
1
- # Repository Skill Distribution
2
-
3
- Use this reference when adding Ankhorage-owned skills to repositories or changing Devtools
4
- synchronization.
5
-
6
- ## Canonical destination
7
-
8
- Repository-local skills live at:
9
-
10
- ```text
11
- .agents/
12
- skills/
13
- <skill-name>/
14
- SKILL.md
15
- agents/ # optional
16
- references/ # optional
17
- scripts/ # optional
18
- assets/ # optional
19
- ```
20
-
21
- The directory name must equal the skill's frontmatter `name`. Synchronize the complete skill
22
- directory, not only `SKILL.md`. Do not use `.agent/`, `.codex/skills/`, or a package source
23
- directory as the shared repository location.
24
-
25
- ## Devtools ownership
26
-
27
- `@ankhorage/devtools` is the distribution authority for canonical Ankhorage-owned repository
28
- skills. It packages immutable skill sources with the released Devtools version; synchronization
29
- must not fetch mutable files from GitHub at runtime.
30
-
31
- The aggregate commands include the skills scope:
32
-
33
- ```text
34
- ankh devtools sync [target]
35
- ankh devtools status [target]
36
- ```
37
-
38
- Also expose focused commands for diagnosis and intentional updates:
39
-
40
- ```text
41
- ankh devtools skills sync [target]
42
- ankh devtools skills status [target]
43
- ```
44
-
45
- Their provider capabilities are `devtools.skills.sync` and `devtools.skills.status`.
46
-
47
- ## Skill selection
48
-
49
- Do not copy every available skill into every repository.
50
-
51
- - Devtools defines a small baseline of organization-wide Ankhorage skills.
52
- - Profile-specific Ankhorage skills are selected from repository traits or explicit package
53
- metadata when automatic detection would be ambiguous.
54
- - External, personal, experimental, and task-specific skills are not part of Devtools sync.
55
- - A repository may own additional skill directories beside the Devtools-managed set.
56
-
57
- The `zora-designer` profile skill is selected for the ZORA, Templates, and Studio owners and for
58
- generated-app authoring repositories that consume ZORA with the Ankhorage Runtime, Templates, or
59
- Studio application model. Plain libraries and unrelated tooling packages retain only baseline
60
- skills.
61
-
62
- Prefer the same repository-trait detection used by other Devtools profiles. Add explicit metadata
63
- only for an actual ambiguity; do not require each repository to repeat a default skill list.
64
-
65
- ## Managed-tree semantics
66
-
67
- Treat each selected canonical skill as an exactly managed directory while preserving the rest of
68
- `.agents/skills/`.
69
-
70
- - Create or replace every canonical file in a selected managed skill.
71
- - Remove stale files and obsolete skills only when prior Devtools ownership is recorded.
72
- - Never delete an unowned skill directory or an untracked file merely because it is absent from
73
- the Devtools bundle.
74
- - Record the managed skill names, relative file paths, source Devtools version, and content hashes
75
- in a Devtools ownership manifest.
76
- - Make `sync` idempotent. Make `status` and `--dry-run` report created, updated, removed, and
77
- unchanged paths without mutation.
78
-
79
- The ordinary single-file managed-file abstraction is insufficient if it cannot report or remove
80
- stale owned files. Use a managed-tree abstraction or extend the ownership manifest rather than
81
- deleting `.agents/skills/` wholesale.
82
-
83
- ## Suggested Devtools source layout
84
-
85
- Keep the package-level CLI edge separate from synchronization policy and packaged skill assets:
86
-
87
- ```text
88
- src/
89
- cli/
90
- commands.ts
91
- runRepositoryCommand.ts
92
- tools/
93
- skills/
94
- index.ts
95
- managed.ts
96
- selection.ts
97
- assets/
98
- <skill-name>/
99
- SKILL.md
100
- ...
101
- ```
102
-
103
- The exact filenames may follow the existing Devtools conventions. The important boundaries are:
104
-
105
- - `src/cli/` declares and dispatches `skills sync` and `skills status`;
106
- - skill selection and managed-tree policy stay outside the CLI;
107
- - packaged skill directories are release artifacts, not runtime network dependencies.
108
-
109
- ## Validation
110
-
111
- Doctor should validate that:
112
-
113
- - every selected managed skill exists at `.agents/skills/<skill-name>/`;
114
- - directory and frontmatter names agree;
115
- - managed files match the released Devtools bundle;
116
- - the ownership manifest contains no unsafe paths;
117
- - repository-owned skills remain permitted and are not falsely reported as drift.
118
-
119
- Devtools remains responsible for applying and reporting synchronization. Doctor reports contract
120
- violations; it does not rewrite skill trees.
@@ -1,180 +0,0 @@
1
- # Studio Structure Example
2
-
3
- Read this only for `ankhorage/studio`. It is a structural target and ownership checklist, not a
4
- license to move every file in one change.
5
-
6
- Studio is the bounded capability. `features/` is its internal organizational boundary; its contents
7
- are not independently bound packages.
8
-
9
- ## Target source tree
10
-
11
- ```text
12
- src/
13
- index.ts
14
- root.ts
15
-
16
- cli/ # one Studio Ankh provider
17
- host/ # Bun/Fastify/filesystem edges and host composition
18
- apps/ # generated applications; Studio-only directory
19
- <generated-app>/ # generated; never edited by hand
20
- studio/ # temporary exception until Studio is generated
21
-
22
- features/ # Studio-owned capabilities
23
- auth/
24
- bindings/
25
- canvas/
26
- deploy/
27
- diagnostics/
28
- external-apis/
29
- manifest/
30
- media/
31
- modules/
32
- projects/
33
- properties/
34
- routes/
35
- secrets/
36
- selection/
37
- templates/
38
- workspace/
39
-
40
- utils/ # the canonical Studio-local utility directory
41
-
42
- test/
43
- acceptance/
44
- e2e/
45
- fixtures/
46
- smoke/
47
- ```
48
-
49
- `index.ts`, `root.ts`, `cli/`, `host/`, `apps/`, `features/`, and `utils/` are the complete Studio
50
- root taxonomy, apart from required declaration shims. Do not create `app/`, `platform/`, `common/`,
51
- `core/`, `helpers/`, or `shared/`.
52
-
53
- Substantial features may contain `contracts`, `domain`, `application`, `ports`, `adapters`, and
54
- focused colocated `tests` when those roles genuinely exist. Do not pre-create role directories.
55
-
56
- `apps/` contains complete generator-owned applications. Nothing under it is manually maintained.
57
- `apps/studio/` is a temporary exception while Studio is still hand-authored; it must disappear when
58
- the Studio app is generated.
59
-
60
- `utils/` is the one canonical local utility directory. It contains only reusable Studio-local,
61
- framework-neutral helpers; behavior with feature semantics remains in that feature, and behavior
62
- reused across repositories belongs in `@ankhorage/utility`.
63
-
64
- ## Studio CLI
65
-
66
- The command tree mirrors paths after the `studio` prefix:
67
-
68
- ```text
69
- src/cli/
70
- index.ts
71
- commands/
72
- dev.ts
73
- projects/
74
- create.ts
75
- delete.ts
76
- list.ts
77
- sync.ts
78
- ```
79
-
80
- Mappings:
81
-
82
- ```text
83
- ankh studio dev -> commands/dev.ts
84
- ankh studio projects create -> commands/projects/create.ts
85
- ankh studio projects delete -> commands/projects/delete.ts
86
- ankh studio projects list -> commands/projects/list.ts
87
- ankh studio projects sync -> commands/projects/sync.ts
88
- ```
89
-
90
- `cli/commands/` contains inbound adapters only: parse command input, invoke a feature application
91
- operation, and render the result. It must not own feature rules or external-package integrations.
92
-
93
- ## Studio host
94
-
95
- ```text
96
- src/host/
97
- createStudioHost.ts
98
- middleware/
99
- routes/
100
- <feature>/
101
- ```
102
-
103
- `host/` contains inbound HTTP, filesystem, and process adapters plus their composition. Route and
104
- middleware modules translate into feature application operations; they do not own feature rules.
105
-
106
- `ankh studio workspace install` is not part of the target. Generated apps are standalone and own
107
- their installation. Remove the obsolete command, handler, capability, tests, and documentation
108
- rather than relocating them.
109
-
110
- ## Current directory disposition
111
-
112
- - Root `binding*` modules move into `features/bindings/`.
113
- - Root `canvas*` and insert/placement behavior move into `features/canvas/`.
114
- - Root `projectDeploy*`, host deploy code, deploy routes, and deploy UI converge under
115
- `features/deploy/`, with host routes remaining in `host/routes/deploy/`.
116
- - Root auth settings/health/OAuth behavior and host auth implementations converge under
117
- `features/auth/`, with host routes remaining in `host/routes/auth/`.
118
- - Root external API contracts/model code, host API services, routes, and UI converge under
119
- `features/external-apis/`, with host routes remaining in `host/routes/external-apis/`.
120
- - Root media authoring code, host media implementations, and media UI converge under
121
- `features/media/`.
122
- - Root module admin code and host module integration converge under `features/modules/`.
123
- - Root project/workspace models, project screens, hooks, project store/generation operations, and
124
- matching adapters converge under `features/projects/`, `features/templates/`, or
125
- `features/workspace/` according to actual ownership.
126
- - Root secret API/usage/response behavior and host secret implementations converge under
127
- `features/secrets/`, with host routes remaining in `host/routes/secrets/`.
128
- - Route and admin-route policy moves under `features/routes/`; the corresponding host adapters stay
129
- in `host/routes/`.
130
- - Selection, measurement, stationary selection, and canvas interaction behavior must be separated
131
- between `features/selection/` and `features/canvas/` by actual invariant ownership.
132
- - The current generic `core/` directory disappears; each file moves to its owning feature role or
133
- package edge.
134
- - The current generic `runtime/` directory is reviewed symbol by symbol. Shared runtime behavior
135
- moves to `@ankhorage/runtime`; Studio-specific integration becomes a feature-local adapter.
136
- - Feature-specific UI becomes generated-app code under `apps/`; it is never rehomed in a generic
137
- Studio UI directory.
138
- - Host smoke and acceptance infrastructure moves outside production source to `test/`.
139
-
140
- ## External package integrations
141
-
142
- An Ankhorage or third-party package is connected in the owning feature, not in a global
143
- `platform/` directory. For example:
144
-
145
- ```text
146
- src/features/templates/
147
- ports/
148
- templateCatalogPort.ts
149
- adapters/
150
- createAnkhorageTemplatesAdapter.ts
151
- ```
152
-
153
- The port states the capability that Templates requires. The adapter imports
154
- `@ankhorage/templates`, translates its API, and implements that port. The composition root chooses
155
- the adapter. Do not duplicate an adapter in `host/`, `cli/`, or another feature.
156
-
157
- ## Utility gates
158
-
159
- The existing own-property helpers explicitly marked for Utility extraction should move through
160
- `@ankhorage/utility` before Studio consumes them. Repeated generic unknown-value narrowing should
161
- be evaluated under `@ankhorage/utility/object` or `@ankhorage/utility/value`; semantic payload
162
- parsers remain domain-owned.
163
-
164
- ## Suggested migration order
165
-
166
- Use lower-entanglement domains to prove the structure before moving the largest state models:
167
-
168
- 1. external APIs;
169
- 2. modules;
170
- 3. media;
171
- 4. secrets;
172
- 5. projects and templates;
173
- 6. deploy;
174
- 7. auth;
175
- 8. canvas and selection;
176
- 9. routes;
177
- 10. manifest.
178
-
179
- Reassess cross-package ownership during every unit. Moving a misplaced behavior deeper into Studio
180
- is not a successful migration when another Ankhorage package owns it.
@@ -1,62 +0,0 @@
1
- # Utility Ownership and Unknown-Value Narrowing
2
-
3
- Classify a helper before creating or moving it:
4
-
5
- ```text
6
- cross-repository, framework-neutral -> @ankhorage/utility/<category>
7
- cross-domain inside one package -> src/utils/<functionName>.ts
8
- one domain only -> src/<domain>/utils/<functionName>.ts
9
- semantic/domain behavior -> owning domain, not utils
10
- ```
11
-
12
- Do not retain local copies while waiting for a Utility release. Follow the Utility repository's
13
- current PR, merge, release, and dependency-update workflow.
14
-
15
- ## Strong cross-repository candidates
16
-
17
- Generic object and unknown-value operations commonly belong in focused Utility subpaths:
18
-
19
- ```text
20
- @ankhorage/utility/object
21
- readOwnProperty
22
- setOwnProperty
23
- deleteOwnProperty
24
- isRecord
25
-
26
- @ankhorage/utility/value
27
- asString
28
- asNumber
29
- asRecord
30
- ```
31
-
32
- Create public utilities only after confirming repetition and stable semantics across repositories.
33
- Do not move feature payload parsers, provider response semantics, or domain validation merely
34
- because they contain small type guards.
35
-
36
- ## Absence and failure semantics
37
-
38
- Use consistent meanings:
39
-
40
- - `isRecord(value)` returns a type-guard boolean.
41
- - `asRecord(value)` returns the narrowed record or `undefined`.
42
- - `asString(value)` returns the string or `undefined`.
43
- - `readOwnProperty(target, key)` returns the owned value or `undefined`.
44
- - `parse<DomainValue>(value)` returns an explicit domain parse result when callers need to
45
- distinguish absent, invalid, and valid values.
46
-
47
- Reserve `null` for an intentional domain or serialized value. Do not use `null` as the generic
48
- failure result for type narrowing when `undefined` expresses absence. When failure details matter,
49
- use a discriminated result instead of alternating between `null` and `undefined`.
50
-
51
- ## Avoid false utilities
52
-
53
- Keep these with their owner:
54
-
55
- - `readProjectDeployConfig`
56
- - `readSecretPayload`
57
- - `parseStudioModuleState`
58
- - API response validation with feature-specific error policy
59
- - helpers that encode manifest, route, auth, deploy, or provider semantics
60
-
61
- A utility is not a place to hide complexity or shorten a file. It must represent a reusable,
62
- cohesive capability with stable behavior.