Dist-Conformance

 view release on metacpan or  search on metacpan

lib/Dist/Conformance/Check/ClaudeSettings.pm  view on Meta::CPAN

package Dist::Conformance::Check::ClaudeSettings 0.003;

# ABSTRACT: .claude/settings.json enables the plugins of the harness

use 5.040;
use warnings FATAL => 'all';
use re '/aasx';
use Mojo::Base 'Dist::Conformance::Check', -signatures;

use Cpanel::JSON::XS();

use Dist::Conformance::Schema();


sub config_schema ($) {
    return {
        required   => [qw{file plugins}],
        properties => {
            file    => $Dist::Conformance::Schema::PATH,
            plugins => { type => 'array', items => { type => 'string', pattern => '\A[^@\s]+@[^@\s]+\z' } },
            missing => { %$Dist::Conformance::Schema::STATUS, default => 'fail' },
        },
    };
}


sub settings ( $self, $snapshot ) {
    my $file = $self->config->{file};
    my $text = $snapshot->content($file) // return undef;
    return Dist::Conformance::Schema::parse_json( $text, $file );
}


sub disabled ( $self, $settings ) {
    my $enabled  = ref $settings->{enabledPlugins} eq 'HASH' ? $settings->{enabledPlugins} : {};
    my @disabled = grep { !$enabled->{$_} } @{ $self->config->{plugins} };
    return @disabled;
}


sub check ( $self, $snapshot ) {
    my ( $file, $missing ) = @{ $self->config }{qw{file missing}};
    my $settings = eval { $self->settings($snapshot) };
    return ( 'fail',   Dist::Conformance::Schema::first_line($@) ) if $@;
    return ( $missing, "$file is missing" )                        if !$settings;
    my @disabled = $self->disabled($settings);
    return ( $missing, 'does not enable ' . join ', ', @disabled ) if @disabled;
    return ( 'pass',   'enables ' . join ', ',         @{ $self->config->{plugins} } );
}


sub update ( $self, $update ) {
    my $settings = eval { $self->settings( $update->snapshot ) };
    if ($@) {
        $update->by_hand( Dist::Conformance::Schema::first_line($@) . ': fix it by hand' );
        return;
    }
    $settings //= {};
    my @disabled = $self->disabled($settings);
    return if !@disabled;
    $settings->{enabledPlugins}     = {} if ref $settings->{enabledPlugins} ne 'HASH';
    $settings->{enabledPlugins}{$_} = Cpanel::JSON::XS::true() for @disabled;
    $update->write( $self->config->{file}, Dist::Conformance::Schema::encode_json($settings) );
    return;
}

__END__

=pod

=encoding UTF-8

=head1 NAME

Dist::Conformance::Check::ClaudeSettings - .claude/settings.json enables the plugins of the harness

=head1 VERSION

version 0.003

=head1 DESCRIPTION

Claude Code loads a plugin for a repository when the project settings enable
it, under C<enabledPlugins>, as C<plugin@marketplace>.  The check passes when
the file enables each plugin of C<plugins>.  It reports C<missing> when the
file is absent or does not enable one, and fails when the file does not parse
as a JSON object, which Claude Code would not read either.

The update writes the file when it is absent, and sets each plugin to C<true>
in C<enabledPlugins> when it is there.  It keeps every other key of the file,
and writes it with sorted keys and an indent of two.  A file that does not
parse is left for a person.

=head1 METHODS

=head2 settings

C<($snapshot)>.  The parsed settings, C<undef> when the file is absent.  Dies
when it does not parse.

=head2 disabled

C<($settings)>.  The plugins that C<$settings> does not enable.

=head2 check

=head2 update

Writes the settings, or enables the plugins in them.

=head1 IN A FLAVOR



( run in 1.063 second using v1.01-cache-2.11-cpan-1236ad508bc )