view release on metacpan or search on metacpan
.claude/agents/api-docker-engine-worker.md view on Meta::CPAN
description: "Docker Engine API specialist for API::Docker â use whenever the question is what the daemon does or expects: adding or correcting an endpoint, query-parameter and filter semantics, response shapes (204/304, NDJSON event streams, error...
model: inherit
allowed-tools: Read, Edit, Write, Bash, Glob, Grep
briefing:
skills:
- docker-engine-api
- api-docker-core
- getty-perl-core
- getty-perl-moo
- getty-perl-release-author-getty
- getty-git-commit-style
- kanban-issues-karr-cli
---
You are the api-docker-engine-worker for **API::Docker**.
Your lane is the boundary between this distribution and the Docker Engine: what the
daemon accepts, what it answers, and whether this client models that faithfully.
Everything that is a Perl or packaging question â Moo structure, the socket and chunked
reader, refactoring, `cpanfile`, dist plumbing â belongs to `api-docker-worker`; hand it
over rather than drifting into it. The conventions above are non-negotiable â apply
.claude/agents/api-docker-type-writer.md view on Meta::CPAN
model: inherit
allowed-tools: Read, Edit, Write, Bash, Glob, Grep
briefing:
skills:
- api-docker-type-model
- api-docker-core
- docker-engine-api
- getty-perl-core
- getty-perl-moo
- getty-perl-release-author-getty
- getty-git-commit-style
- kanban-issues-karr-cli
---
You are the api-docker-type-writer for **API::Docker**.
Your lane is the type model: the swagger in `spec/`, the `API::Docker::Type` DSL and its
registry, the generated classes, and the drift checker that keeps them honest. The
transport, the resource classes and the tests belong to `api-docker-worker`,
`api-docker-engine-worker` and `api-docker-test-writer` â hand those over rather than
drifting into them. The conventions above are non-negotiable â apply silently, do not
.claude/agents/api-docker-worker.md view on Meta::CPAN
description: "Default API::Docker worker â the Perl side of this distribution: Moo classes and roles, the socket and HTTP/1.1 transport internals (chunked reading, header assembly, status handling), entity wrappers, refactoring, cpanfile and dist p...
model: inherit
allowed-tools: Read, Edit, Write, Bash, Glob, Grep
briefing:
skills:
- api-docker-core
- getty-perl-core
- getty-perl-moo
- getty-perl-release-author-getty
- perl-release-dist-ini
- getty-git-commit-style
- kanban-issues-karr-cli
---
You are the api-docker-worker for **API::Docker**.
Implement, refactor, debug, and test the Perl side of this distribution. The conventions
above are non-negotiable â apply silently, do not restate.
**Where your lane ends.** You own how this distribution is built: `Role::HTTP`'s socket
handling and chunked reader, Moo composition, the entity roles composed onto the
.claude/rules/api-docker-rules.md view on Meta::CPAN
Apply to every task in this distribution unless explicitly overridden. Bias: caution over
speed on non-trivial work; use judgment on trivial tasks. Loaded automatically at launch
(same priority as `CLAUDE.md`). Subagents get their discipline from the skills
force-loaded via `briefing.skills` â this file is for the orchestrating agent.
## Engineering discipline
1. **Think before coding** â state assumptions; when uncertain, ask rather than guess.
Push back when a simpler approach exists.
2. **Simplicity first** â minimum code that solves the problem. Nothing speculative.
3. **Surgical changes** â touch only what you must. Match existing style.
4. **Goal-driven execution** â define success criteria, loop until verified.
5. **Surface conflicts, don't average them** â pick one (more recent / more tested), flag
the other for cleanup. Don't blend.
6. **Read before you write** â `Role::HTTP` is the single seam every resource API and
entity class hangs off. A change to `_request`'s options, return shape or error
handling reaches every module in `lib/` and the mock harness at once.
7. **Tests verify intent, not just behavior** â a test that can't fail when the logic
changes is wrong, and a helper that normalises its input before asserting is that
test. Reproduce a bug before fixing it; leave the regression behind.
8. **Checkpoint after every significant step** â summarize: done / verified / left.
.claude/rules/api-docker-rules.md view on Meta::CPAN
- **`[@Author::GETTY]` gathers through `Git::GatherDir`, which sees only tracked
files.** A new `.pm`, test file or fixture is invisible to `dzil build`/`dzil test`
until it is `git add`-ed â while `prove -lr t/` stays green the whole time, because it
reads `lib/` and `t/` directly rather than through the gathered file list. A `dzil
build` failure that looks like a missing module, or a passing `prove` next to a
failing `dzil test`, is this before anything else: check `git status` for an untracked
file first.
## Perl specifics â reference, don't restate
Module loading, `$VERSION`, cpanfile pinning and house style: skills `getty-perl-core`,
`getty-perl-moo`. `[@Author::GETTY]`, POD weaving, `{{$NEXT}}`: skill
`getty-perl-release-author-getty`. dist.ini mechanics: `perl-release-dist-ini`. Commit
messages: `getty-git-commit-style`. Architecture and transport invariants:
`api-docker-core`. What the daemon itself does â wire formats, response shapes, filters,
registry auth: `docker-engine-api` (briefed only into the engine-worker and the
test-writer). Don't duplicate any of it here.
.claude/skills/getty-git-commit-style/SKILL.md view on Meta::CPAN
---
name: getty-git-commit-style
description: Use when writing or amending a commit message in a Getty repository, including a commit that spans several repos.
---
# Commit Message Style
## Format
```
<summary line â imperative, max ~72 chars>
.claude/skills/getty-perl-core/SKILL.md view on Meta::CPAN
## Control flow
- **Postfix `if`/`unless`** for guards and short conditions: `croak(...) if $self->readonly;`
- **`unless $x`** instead of `if !$x`.
- **Guard clauses return bare:** `return unless $res->is_success;` â not `return undef;`.
- **Nested ternaries** for a return that picks between expressions, instead of an if/elsif chain.
## Data
- **`{ %hash }` and `\%hash` are different operations, not two styles.** `{ %h }` builds a new anonymous copy; `\%h` references the existing hash. Return a copy when the caller must not mutate your state; return the reference when sharing is the poin...
- **`Path::Tiny`** for every file operation â not `File::Spec`, not bare `open`. `path(...)->child(...)->slurp_utf8`.
- **`JSON::MaybeXS`** always â never `JSON::PP`, `JSON::XS`, `Cpanel::JSON::XS` directly. Encoders get `canonical => 1, convert_blessed => 1`.
- **Every serialiser is deterministic.** MessagePack `->canonical`, DBIC `serializer_options => { canonical => 1 }`. Same rule, every format.
- **Booleans: `JSON->true` / `JSON->false`.** `use JSON::MaybeXS;` covers codec and booleans.
- `$YAML::XS::Boolean = 'JSON::PP'` is one of YAML::XS's fixed mode names, not a module choice â leave it alone.
- **Align `=>` in multi-line hash literals** when keys are of similar length.
- **Optional pairs inline:** `$cond ? ( experimental => 1 ) : (),`
## Configuration
.claude/skills/getty-perl-core/SKILL.md view on Meta::CPAN
# â GETTY/Module-Name-1.234.tar.gz â pin to 1.234
```
Getty-authored (non-exhaustive): `Langertha`, `IO::K8s`, `Kubernetes::REST`, `WWW::Crawl4AI`, `Net::Async::Crawl4AI`, `Net::Async::WebSearch`, `Catalyst::Plugin::ChainedURI`, `Locale::Simple`, `DBIO::*`, `WWW::Zitadel`, `WWW::PayPal`, `WWW::Chain`.
## Changelog (the Changes file)
Every distribution ships a `Changes` file with a `{{$NEXT}}` token at the top (Dist::Zilla's `[NextRelease]` fills it at release time).
- **Add a bullet under `{{$NEXT}}` in the SAME commit as any user-facing change** â new bindings, behaviour changes, bug fixes, deprecations. If a CPAN consumer would notice, it belongs there.
- **Match the existing style:** two-space indent, ` - ` bullets, wrap near 78 columns, present-tense imperative ("New binding X", "Fix Y on macOS").
- **One topic, one bullet, one to three lines** â touching an area again rewrites the bullet that is already there instead of adding a second. Wording and length: `getty-git-commit-style`.
- **Skip pure dev-tooling noise** â skill hardlinks, editor config, internal CI refactors. A CI fix that unbreaks the build for everyone IS worth a line.
- **Never hand-edit the version line or timestamp** â `[NextRelease]` owns those.
## Forbidden
â `require Foo` inside a method to "speed up startup" · â a Getty repo's `$VERSION` as a cpanfile requirement · â `'0'` or `'>= x'` as a version argument · â `default => sub {...}` for a non-trivial attribute default · â 4-space indent ...
## When in doubt
Grep hand-written Getty code for how the pattern is used there â the reference is an older repo with no AI commits in its history. Newer repos may show an agent's guess rather than the house rule.
.claude/skills/getty-perl-moo/SKILL.md view on Meta::CPAN
- Moose class can `extends` a Moo class
- Moo class can `with` a Moose role
```perl
BEGIN { require Moose }
package MyMooseClass;
use Moose;
extends 'MyMooClass'; # works if Moose was loaded first
```
For Moose-style syntax in Moo (`isa => 'Str'`, `lazy_build`), use `MooX::late`. Avoid `Any::Moose` â deprecated, points to Moo.
---
## Type Constraints
Moo has no built-in type system â `isa` takes a coderef, and `Type::Tiny` objects
are coderefs, so `Types::Standard` plugs straight in:
```perl
use Types::Standard qw( Str ArrayRef );
.claude/skills/getty-perl-moo/SKILL.md view on Meta::CPAN
| Situation | Use |
|---|---|
| Shared attributes/methods, stable "is-a" | `extends` |
| Optional/horizontal feature | `Moo::Role` + `with` |
| Same pattern, different config | `MooX::Role::Parameterized` |
| Delegate method set to sub-object | `handles` |
| Array/Hash operations on attribute | `Sub::HandlesVia` |
| Logging/validation/caching wrapper | `before`/`around`/`after` |
| Catch constructor typos | `MooX::StrictConstructor` |
| Cross-project boilerplate | `Import::Into` house-style module |
| Named types | `Type::Tiny` / `Types::Standard` |
| Multiple roles define same method | Sequential `with` or refactor |
| Legacy non-Moo parent | `FOREIGNBUILDARGS` |
| Multiple inheritance | Last resort; use `mro 'c3'` |
---
## Common Pitfalls
- `default => []` â **shared state bug**. Always `default => sub { [] }`.
.claude/skills/getty-perl-release-author-getty/SKILL.md view on Meta::CPAN
effect.
## Release Workflow
```bash
dzil release # Builds, tests, uploads to CPAN, bumps version, commits, tags
```
Read the `{{$NEXT}}` section of `Changes` once as a whole first. It was written bullet
by bullet over weeks, so this is where entries circling one topic get merged into one
and over-detailed ones get cut back (skill `getty-git-commit-style`). It is not only a
changelog: `GitHub::CreateRelease` runs with `notes_from = ChangeLog` and publishes the
section verbatim as the release notes.
Fix it in its own commit *before* `dzil release`. `Changes` sits in the release commit's
`allow_dirty` list, so an uncommitted edit stops nothing â it is folded into the release
snapshot silently, under a message naming only the version.
## Conventions
1. `copyright_year` IS used in dist.ini â GETTY has it in ALL distributions, do NOT remove it
.claude/agents/api-docker-test-writer.md
.claude/agents/api-docker-type-writer.md
.claude/agents/api-docker-worker.md
.claude/rules/api-docker-rules.md
.claude/settings.json
.claude/skills/api-docker-core/SKILL.md
.claude/skills/api-docker-type-model/SKILL.md
.claude/skills/api-docker-type-model/references/dsl.md
.claude/skills/api-docker-type-model/references/types.md
.claude/skills/docker-engine-api/SKILL.md
.claude/skills/getty-git-commit-style/SKILL.md
.claude/skills/getty-perl-core/SKILL.md
.claude/skills/getty-perl-moo/SKILL.md
.claude/skills/getty-perl-release-author-getty/SKILL.md
.claude/skills/kanban-issues-karr-cli/SKILL.md
.claude/skills/perl-release-dist-ini/SKILL.md
.gitignore
CLAUDE.md
Changes
LICENSE
MANIFEST
t/system_auth.t view on Meta::CPAN
'and an already-encoded X-Registry-Auth value is decoded back into it';
my $j = fake_client();
$j->system->auth(auth => '{"identitytoken":"tok-123"}');
is_deeply decode_json(request_body($j->written)), { identitytoken => 'tok-123' },
'as is a raw JSON AuthConfig';
};
# ---------------------------------------------------------------------------
subtest 'the two spellings may not be mixed' => sub {
# Not a style rule: picking one silently would be picking which of two sets
# of credentials gets sent.
my $c = fake_client();
ok !eval { $c->system->auth(auth => $CREDS, username => 'other'); 1 },
'auth => $config beside a credential key croaks';
like $@, qr/not both/, 'and says which keys were seen';
is $c->written, '', 'nothing was sent';
};
# ---------------------------------------------------------------------------
subtest 'a check with nothing to check croaks before the request' => sub {
'a 1.44 field on a 1.41 engine is still sent -- Podman serves fields its '
. 'announced version does not promise, and refuses ones it does');
};
# ---------------------------------------------------------------------------
# The wire name is derived from the Perl name, and the spec's spelling wins
# ---------------------------------------------------------------------------
subtest 'wire names' => sub {
my $reg = API::Docker::Type::Resources->docker_attributes;
is($reg->{cpu_shares}{wire}, 'CpuShares', 'port_bindings-style derivation');
is($reg->{nano_cpus}{wire}, 'NanoCpus', 'derivation covers most fields');
is($reg->{oom_kill_disable}{wire}, 'OomKillDisable', 'and multi-word ones');
is($reg->{kernel_memory_tcp}{wire}, 'KernelMemoryTCP',
'a spelling the derivation cannot reach is declared explicitly');
is($reg->{io_maximum_iops}{wire}, 'IOMaximumIOps', 'likewise IOMaximumIOps');
is($reg->{blkio_device_read_iops}{wire}, 'BlkioDeviceReadIOps',
'likewise BlkioDeviceReadIOps');
is(API::Docker::Type::Port->docker_attributes->{ip}{wire}, 'IP',
'and a two-letter all-caps name');
is(API::Docker::Type::HostConfig->docker_attributes->{uts_mode}{wire}, 'UTSMode',