API-Docker

 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

MANIFEST  view on Meta::CPAN

.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 {

t/type.t  view on Meta::CPAN

    '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',



( run in 1.263 second using v1.01-cache-2.11-cpan-7e1922ba9f2 )