Skip to content
Open
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
ee20fa7
feat: Set up agent skills management architecture
reidbaker Jun 17, 2026
26b37ae
feat: Add check-readiness skill
reidbaker Jun 17, 2026
d825767
feat: Add local check-readiness skill and configure linter
reidbaker Jun 17, 2026
f7f0646
test: ensure tracked skills cannot be published accidentally
reidbaker Jun 17, 2026
ea27e43
build: pin dart_skills_lint to support individual_skills
reidbaker Jun 17, 2026
9ac31a2
test: rewrite tracked skills test to use ValidationSession API
reidbaker Jun 17, 2026
87cfaf1
test: fix analyzer warnings
reidbaker Jun 17, 2026
acbcc3e
build: update dart_skills_lint to 8f85e82b on main
reidbaker Jun 18, 2026
7eabf5f
test: rewrite tracked skills test to use yaml parsing, address PR com…
reidbaker Jun 18, 2026
9e0d9e5
test: revert yaml parsing, use public ValidationSession from repo
reidbaker Jun 18, 2026
6b68664
test: revert to ValidationSession and use ignore implementation_imports
reidbaker Jun 18, 2026
0942453
test: replace yaml parsing with custom skill rule EnforceTrackedSkill…
reidbaker Jun 18, 2026
9471107
test: extract EnforceTrackedSkillsInternalRule to its own file with docs
reidbaker Jun 18, 2026
c4e832f
ci: allow dart_skills_lint in packages
reidbaker Jun 18, 2026
acc34a5
test: fix internal rule validation feedback
reidbaker Jun 18, 2026
288e5ec
Fix missing copyright headers in check-readiness agent skill
reidbaker Jun 19, 2026
43be3d1
Support .pubignore in publish-check
reidbaker Jun 19, 2026
8d17949
Add tests for publish_check pubignore parsing
reidbaker Jun 19, 2026
81c1c52
Fix .gitignore for check-readiness skill and symlinked skills
reidbaker Jun 19, 2026
438537c
Revert un-ignoring of symlinked skills
reidbaker Jun 19, 2026
f64190b
Add TODO for tracking dart-lang/pub issue 4841
reidbaker Jun 19, 2026
14d7cfc
Group pubignore tracking tests under issue 4841
reidbaker Jun 19, 2026
d7f024e
Move TODO out of group name
reidbaker Jun 19, 2026
bc37ae6
Fix analyzer warnings
reidbaker Jun 19, 2026
16e3f28
Fix .gitignore un-ignore rule overreach
reidbaker Jun 19, 2026
83638ff
Rename EnforceTrackedSkillsInternalRule to EnforceTrackedSkillsPreven…
reidbaker Jun 22, 2026
d93c81e
Move third-party skills to third_party/skill-repos/ and update symlin…
reidbaker Jun 22, 2026
7c080f9
Move third-party README to third_party/skill-repos/ and update refere…
reidbaker Jun 22, 2026
51ecf16
Canonicalize paths for EnforceTrackedSkillsPreventPublishingRule to f…
reidbaker Jun 22, 2026
2271f28
Add path dependency to camera_android_camerax dev_dependencies
reidbaker Jun 22, 2026
da6b889
feat: migrate check-readiness skill from bash to dart with comprehens…
reidbaker Jun 18, 2026
0129f97
address code review feedback
reidbaker Jun 19, 2026
4169386
Fix dart analyze behavior for .agents/skills
reidbaker Jun 19, 2026
f17e516
Support .pubignore parsing in flutter_plugin_tools to skip hygiene ch…
reidbaker Jun 19, 2026
6c9ec74
Merge remote-tracking branch 'origin/main' into convert-check-sh-to-dart
reidbaker Jun 22, 2026
a2d86d0
Remove migrated check.sh script
reidbaker Jun 22, 2026
abd0a6b
Format code
reidbaker Jun 22, 2026
d92048e
Exempt .agents/ changes from version and CHANGELOG validations
reidbaker Jun 22, 2026
710a71d
Address code review feedback on pubignore matching and symlink following
reidbaker Jun 22, 2026
f48a349
Remove redundant followLinks argument in analyze_command
reidbaker Jun 22, 2026
60e836a
Resolve all linter warnings in repository_package
reidbaker Jun 22, 2026
4355658
Fix check-readiness license headers and resolve Windows test failure
reidbaker Jun 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .ci/targets/analyze.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ tasks:
script: .ci/scripts/tool_runner.sh
# DO NOT change the custom-analysis argument here without changing the Dart repo.
# See the comment in script/configs/custom_analysis.yaml for details.
args: ["analyze", "--custom-analysis=script/configs/custom_analysis.yaml"]
args: ["analyze", "--custom-analysis=script/configs/custom_analysis.yaml", "--analyze-skills-for=script/configs/skills_analysis.yaml"]
# Re-run analysis with path-based dependencies to ensure that publishing
# the changes won't break analysis of other packages in the respository
# that depend on it.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ metadata:
This skill verifies that the local environment is properly configured and clean before starting new work in the `camera_android_camerax` package.

## Instructions
Run the bundled verification script ([scripts/check.sh](scripts/check.sh)) to perform the automated environment checks:
Run the bundled verification script ([bin/check.dart](bin/check.dart)) to perform the automated environment checks:
```bash
bash .agents/skills/check-readiness/scripts/check.sh
dart run .agents/skills/check-readiness/bin/check.dart
```

### Handling the Results
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:io';

import 'package:check_readiness/check_readiness.dart';

Future<void> main(List<String> args) async {
// Since this tool is executed via `dart run` from the package root,
// the current directory is the workspace root.
final String workspaceRoot = Directory.current.path;

final checker = ReadinessChecker();
final bool isReady = await checker.checkReadiness(workspaceRoot);
exitCode = isReady ? 0 : 1;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:io';

import 'package:file/file.dart';
import 'package:file/local.dart';
import 'package:path/path.dart' as p;
import 'package:process/process.dart';

/// Checks if the environment is ready for new work.
class ReadinessChecker {
/// Creates a new ReadinessChecker.
ReadinessChecker({
FileSystem? fileSystem,
ProcessManager? processManager,
void Function(Object?)? log,
}) : _fileSystem = fileSystem ?? const LocalFileSystem(),
_processManager = processManager ?? const LocalProcessManager(),
_log = log ?? ((Object? msg) => stdout.writeln(msg));

final FileSystem _fileSystem;
final ProcessManager _processManager;
final void Function(Object?) _log;

/// Runs all readiness checks.
///
/// Returns `true` if ready, `false` otherwise.
Future<bool> checkReadiness(String workspaceRoot) async {
_log('Checking if environment is ready for new work...');

if (!await _checkSymlinks(workspaceRoot)) {
return false;
}
if (!await _checkGitState(workspaceRoot)) {
return false;
}
if (!await _checkFlutterAndDart()) {
return false;
}
if (!await _checkDependencies(workspaceRoot)) {
return false;
}

_log('Environment is fully ready!');
return true;
}

Future<bool> _checkSymlinks(String workspaceRoot) async {
_log('1. Checking skill symlinks...');
final Directory agentsDir = _fileSystem.directory(p.join(workspaceRoot, '.agents', 'skills'));
if (!agentsDir.existsSync()) {
// If it doesn't exist, there are no broken symlinks.
_log('All symlinks resolve correctly.');
return true;
}

final brokenLinks = <String>[];
await for (final FileSystemEntity entity
in agentsDir.list(recursive: true, followLinks: false)) {
if (entity is Link) {
final String targetPath = await entity.target();
// Resolve target relative to the link's directory
final String resolvedTargetPath =
p.isAbsolute(targetPath) ? targetPath : p.join(entity.parent.path, targetPath);
if (_fileSystem.typeSync(resolvedTargetPath) == FileSystemEntityType.notFound) {
brokenLinks.add(entity.path);
}
}
}

if (brokenLinks.isNotEmpty) {
_log('Error: Found broken symlinks in .agents/skills:');
brokenLinks.forEach(_log);
return false;
}

_log('All symlinks resolve correctly.');
return true;
}

Future<bool> _checkGitState(String workspaceRoot) async {
_log('2. Checking git state...');
final ProcessResult result;
try {
result = await _processManager.run(
['git', 'status', '--porcelain'],
workingDirectory: workspaceRoot,
);
} on ProcessException catch (e) {
_log('Error: Failed to run git status. Is git installed and on the PATH?');
_log(e.toString());
return false;
}
if (result.exitCode != 0) {
_log('Error: Failed to run git status.');
return false;
}
final String stdoutStr = (result.stdout as String).trim();
if (stdoutStr.isNotEmpty) {
_log(
'Error: Git working directory is not clean. Please commit or stash your changes before starting new work.');
return false;
}
_log('Git working directory is clean.');
return true;
}

Future<bool> _checkFlutterAndDart() async {
_log('3. Checking Flutter and Dart...');
if (!_canRunCommand('flutter')) {
_log("Error: 'flutter' is not on the PATH.");
return false;
}
if (!_canRunCommand('dart')) {
_log("Error: 'dart' is not on the PATH.");
return false;
}
_log('Flutter and Dart are on the PATH.');
return true;
}

bool _canRunCommand(String command) {
// A simple check using ProcessManager's canRun
// NOTE: ProcessManager.canRun exists if we use process package > certain version
// Let's implement a safe check
return _processManager.canRun(command);
}

Future<bool> _checkDependencies(String workspaceRoot) async {
_log('4. Checking dependencies in camera_android_camerax...');
final ProcessResult result = await _processManager.run(
['flutter', 'pub', 'get'],
workingDirectory: workspaceRoot,
);
if (result.exitCode != 0) {
_log('Error: Failed to resolve dependencies.');
return false;
}
_log('Dependencies are resolved and ready.');
return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: check_readiness
description: A tool to check if the repository is ready for new work, intended only for use in the check-readiness skill.
version: 0.1.0
publish_to: none

environment:
sdk: ^3.0.0

dev_dependencies:
build_runner: ^2.15.0
mockito: ^5.7.0
test: ^1.24.0
dependencies:
file: ^7.0.1
path: ^1.9.1
process: ^5.0.5

This file was deleted.

Loading
Loading