Perl PatternsSAFE
The agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.
Overview
The agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.
649b2d7452ebOBSERVED · 2026-09-21What it tells the agent
The instruction file, verbatim from the audited commit — this is the text the model reads, and the surface the audit's instruction layer examines. Quoted here so you can judge it without cloning anything.
---
name: perl-patterns
description: 堅牢でメンテナブルなPerlアプリケーションを構築するためのModern Perl 5.36+のイディオム、ベストプラクティス、規約。
origin: ECC
---
# モダンPerl開発パターン
堅牢でメンテナブルなアプリケーションを構築するためのイディオマティックなPerl 5.36+パターンとベストプラクティス。
## アクティベートするタイミング
- 新しいPerlコードまたはモジュールを書くとき
- イディオム準拠のためにPerlコードをレビューするとき
- レガシーPerlをモダンな標準にリファクタリングするとき
- PerlモジュールのアーキテクチャをDesignするとき
- 5.36以前のコードをモダンなPerlに移行するとき
## 仕組み
これらのパターンをModern Perl 5.36+のデフォルトへのバイアスとして適用する: シグネチャ、明示的なモジュール、集中的なエラー処理、テスト可能な境界。以下の例は出発点としてコピーし、目の前の実際のアプリ、依存スタック、デプロイモデルに合わせて締め付けることを意図している。
## コア原則
### 1. `v5.36`プラグマの使用
単一の`use v5.36`が古い定型文を置き換え、strict、warnings、サブルーチンシグネチャを有効化する。
```perl
# Good: モダンなプリアンブル
use v5.36;
sub greet($name) {
say "Hello, $name!";
}
# Bad: レガシーな定型文
use strict;
use warnings;
use feature 'say', 'signatures';
no warnings 'experimental::signatures';
sub greet {
my ($name) = @_;
say "Hello, $name!";
}
```
### 2. サブルーチンシグネチャ
明確さと自動アリティチェックのためにシグネチャを使用する。
```perl
use v5.36;
# Good: デフォルト値付きシグネチャ
sub connect_db($host, $port = 5432, $timeout = 30) {
# $hostは必須、その他はデフォルトあり
return DBI->connect("dbi:Pg:host=$host;port=$port", undef, undef, {
RaiseError => 1,
PrintError => 0,
});
}
# Good: 可変引数のためのスラーピーパラメータ
sub log_message($level, @details) {
say "[$level] " . join(' ', @details);
}
# Bad: 手動引数アンパック
sub connect_db {
my ($host, $port, $timeout) = @_;
$port //= 5432;
$timeout //= 30;
# ...
}
```
### 3. コンテキスト感度
スカラーvsリストコンテキストを理解する — Perlのコアコンセプト。
```perl
use v5.36;
my @items = (1, 2, 3, 4, 5);
my @copy = @items; # リストコンテキスト: すべての要素
my $count = @items; # スカラーコンテキスト: カウント (5)
say "Items: " . scalar @items; # スカラーコンテキストを強制
```
### 4. 後置逆参照
ネストされた構造で読みやすさのために後置逆参照構文を使用する。
```perl
use v5.36;
my $data = {
users => [
{ name => 'Alice', roles => ['admin', 'user'] },
{ name => 'Bob', roles => ['user'] },
],
};
# Good: 後置逆参照
my @users = $data->{users}->@*;
my @roles = $data->{users}[0]{roles}->@*;
my %first = $data->{users}[0]->%*;
# Bad: 前置逆参照(チェーンで読みにくい)
my @users = @{ $data->{users} };
my @roles = @{ $data->{users}[0]{roles} };
```
### 5. `isa`演算子(5.32+)
中置型チェック — `blessed($o) && $o->isa('X')`を置き換える。
```perl
use v5.36;
if ($obj isa 'My::Class') { $obj->do_something }
```
## エラー処理
### eval/dieパターン
```perl
use v5.36;
sub parse_config($path) {
my $content = eval { path($path)->slurp_utf8 };
die "Config error: $@" if $@;
return decode_json($content);
}
```
### Try::Tiny(信頼性の高い例外処理)
```perl
use v5.36;
use Try::Tiny;
sub fetch_user($id) {
my $user = try {
$db->resultset('User')->find($id)
// die "User $id not found\n";
}
catch {
warn "Failed to fetch user $id: $_";
undef;
};
return $user;
}
```
### ネイティブtry/catch(5.40+)
```perl
use v5.40;
sub divide($x, $y) {
try {
die "Division by zero" if $y == 0;
return $x / $y;
}
catch ($e) {
warn "Error: $e";
return;
}
}
```
## MooによるモダンOO
軽量でモダンなOOにはMooを優先する。メタプロトコルが必要な場合のみMooseを使用する。
```perl
# Good: Mooクラス
package User;
use Moo;
use Types::Standard qw(Str Int ArrayRef);
use namespace::autoclean;
has name => (is => 'ro', isa => Str, required => 1);
has email => (is => 'ro', isa => Str, required => 1);
has age => (is => 'ro', isa => Int, default => sub { 0 });
has roles => (is => 'ro', isa => ArrayRef[Str], default => sub { [] });
sub is_admin($self) {
return grep { $_ eq 'admin' } $self->roles->@*;
}
sub greet($self) {
return "Hello, I'm " . $self->name;
}
1;
# 使用法
my $user = User->new(
name => 'Alice',
email => '[email protected]',
roles => ['admin', 'user'],
);
# Bad: ブレスされたhashref(バリデーションなし、アクセサなし)
package User;
sub new {
my ($class, %args) = @_;
return bless \%args, $class;
}
sub name { return $_[0]->{name} }
1;
```
### Mooロール
```perl
package Role::Serializable;
use Moo::Role;
use JSON::MaybeXS qw(encode_json);
requires 'TO_HASH';
sub to_json($self) { encode_json($self->TO_HASH) }
1;
package User;
use Moo;
with 'Role::Serializable';
has name => (is => 'ro', required => 1);
has email => (is => 'ro', required => 1);
sub TO_HASH($self) { { name => $self->name, email => $self->email } }
1;
```
### ネイティブ`class`キーワード(5.38+、Corinna)
```perl
use v5.38;
use feature 'class';
no warnings 'experimental::class';
class Point {
field $x :param;
field $y :param;
method magnitude() { sqrt($x**2 + $y**2) }
}
my $p = Point->new(x => 3, y => 4);
say $p->magnitude; # 5
```
## 正規表現
### 名前付きキャプチャと`/x`フラグ
```perl
use v5.36;
# Good: 読みやすさのための/xを使った名前付きキャプチャ
my $log_re = qr{
^ (?<timestamp> \d{4}-\d{2}-\d{2} \s \d{2}:\d{2}:\d{2} )
\s+ \[ (?<level> \w+ ) \]
\s+ (?<message> .+ ) $
}x;
if ($line =~ $log_re) {
say "Time: $+{timestamp}, Level: $+{level}";
say "Message: $+{message}";
}
# Bad: 位置キャプチャ(メンテが難しい)
if ($line =~ /^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\s+\[(\w+)\]\s+(.+)$/) {
say "Time: $1, Level: $2";
}
```
### プリコンパイルパターン
```perl
use v5.36;
# Good: 1回コンパイル、複数回使用
my $email_re = qr/^[A-Za-z0-9._%+-]+\@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/;
sub validate_emails(@emails) {
return grep { $_ =~ $email_re } @emails;
}
```
## データ構造
### リファレンスと安全な深いアクセス
```perl
use v5.36;
# ハッシュと配列リファレンス
my $config = {
database => {
host => 'localhost',
port => 5432,
options => ['utf8', 'sslmode=require'],
},
};
# 安全な深いアクセス(どのレベルが欠落してもundefを返す)
my $port = $config->{database}{port}; # 5432
my $missing = $config->{cache}{host}; # undef、エラーなし
# ハッシュスライス
my %subset;
@subset{qw(host port)} = @{$config->{database}}{qw(host port)};
# 配列スライス
my @first_two = $config->{database}{options}->@[0, 1];
# 複数変数のforループ(5.36で実験的、5.40で安定)
use feature 'for_list';
no warnings 'experimental::for_list';
for my ($key, $val) (%$config) {
say "$key => $val";
}
```
## ファイルI/O
### 3引数open
```perl
use v5.36;
# Good: autodieを使った3引数open(コアモジュール、'or die'を排除)
use autodie;
sub readTrust audit
SAFEgrade B · trust 89/100 Nothing in the source contradicts what it says it does. Grade A is reserved for packages that have also passed the behavioural sandbox.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | PASS |
| L1 | Static analysis of the code | NA |
| L2 | Instruction surface (what it tells the agent) | PASS |
| L3 | Class-specific surface | PASS |
| L4 | Behavioural (sandbox) | SKIPPED |
What the source does
- Filesystem
- none-observed
- Network
- none-observed
- Shell
- none-observed
- Dependencies
- pinned
- Secrets in source
- none-found
Findings (0)
No findings outside the package's declared scope.
Gates applied: no_behavioural_pass.
649b2d7452ebfull audit observations/trust-audit/skill/affaan-m__perl-patterns.json · Report an issue / request a re-scanAudit history
Every audit this skill has had.
| Date | Source | Verdict | Grade | Score | Change |
|---|---|---|---|---|---|
| 2026-09-21 | 649b2d7452eb | SAFE | B | 89 | first audit |
Questions
What does the Perl Patterns skill do?
The agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.
Is Perl Patterns safe to install?
The audit found nothing in the source that contradicts what it says it does, and graded it B (89/100). Grade A is held back for packages that have also passed a sandboxed behavioural run, which is why a clean skill reads B.
What can Perl Patterns access on my machine?
The audit observed no filesystem, network or shell use at all in its source.
How current is this page?
The grade is for one exact copy of the source (649b2d7452eb), read on 2026-09-21. The repository is watched, and a new audit runs when it changes — this is the first audit.