Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
a3366d4
Add workflow lessons library
justin808 Jul 3, 2026
23ed066
Canonicalize readiness vocabulary across batch skills
justin808 Jul 3, 2026
28adc16
Define shared review finding schema
justin808 Jul 3, 2026
31e99f2
Add autoreview target state helper
justin808 Jul 3, 2026
75f72b5
Add optional task observer skill
justin808 Jul 3, 2026
38a08a9
Document knowledge contracts batch
justin808 Jul 3, 2026
73f2d73
Validate review finding contracts
justin808 Jul 3, 2026
0820890
Address knowledge contract review feedback
justin808 Jul 3, 2026
2d0c2c7
Enforce raw solution date format
justin808 Jul 3, 2026
6df5f29
Address final review portability gaps
justin808 Jul 3, 2026
03aed7f
Fix autoreview host marker after rebase
justin808 Jul 5, 2026
1383bc8
Isolate task observer test environment
justin808 Jul 5, 2026
10e442b
Address final PR 69 review findings
justin808 Jul 5, 2026
309cf11
Address final reviewer edge cases
justin808 Jul 5, 2026
287017b
Address dirty review and credential edge cases
justin808 Jul 5, 2026
1304c66
Clarify task observer private URL errors
justin808 Jul 5, 2026
57249ee
Address final closeout review edge cases
justin808 Jul 5, 2026
c96fb0b
Harden task observer sensitive input filtering
justin808 Jul 5, 2026
2fe6947
Address task observer and validator review hardening
justin808 Jul 5, 2026
59530b0
Catch task observer fragment and token leaks
justin808 Jul 5, 2026
3a4a2e6
Reject ambiguous private URL hosts
justin808 Jul 5, 2026
0d5370a
Address final task observer privacy review
justin808 Jul 5, 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ All notable changes to this portable workflow pack are documented here.

#### Added

- **Add durable workflow solution docs, review finding schema, readiness vocabulary, autoreview target-state fixtures, and the optional `task-observer` skill.**
- **Add `agent-workflows-trust-audit` to check recent merged PRs against `pr-security-preflight` and draft candidate repo-local trust entries for maintainer review.**
- **Add `trusted_metadata_bots` so workflow/status bot comments can be audited as metadata without becoming actionable trusted instructions.**
- **Add `pr-security-preflight --strict-trust` so exact-target batches can report actor-trust findings by default while still supporting fail-closed launches.**
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ the managed-vs-repo-owned boundary, and `--root`/`--only`/`--all` usage.
| `run-ci` | Choose and run repo-local CI checks. |
| `spec` | Turn vague implementation intent into requirements, design, and tasks. |
| `status` | Report tight progress (done/in-progress/blocked/next) without starting new work. |
| `task-observer` | Optionally capture sanitized observations for later skill or workflow improvement review. |
| `tdd` | Drive test-first red-green-refactor loops for features and bug fixes. |
| `triage` | Build a whole-surface issue/PR inventory and batch split. |
| `update-changelog` | Classify merged PRs and update a repo changelog. |
Expand Down
74 changes: 71 additions & 3 deletions bin/install-agent-workflows
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ Default targets:
Installed paths:
<target>/skills/*
<target>/workflows/*
<target>/docs/review-finding-schema.md
<target>/docs/solutions/*
<target>/bin/agent-workflow-seam-doctor
<target>/bin/agent-workflows-status
<target>/bin/upgrade-agent-workflows
Expand Down Expand Up @@ -140,11 +142,24 @@ write_metadata() {
mv "$metadata_tmp" "$metadata_path"
}

ensure_real_directory() {
local directory="$1"

if [[ -L "$directory" ]]; then
rm -f "$directory"
fi
if [[ -e "$directory" && ! -d "$directory" ]]; then
echo "Refusing to replace non-directory path: $directory" >&2
exit 1
fi
mkdir -p "$directory"
}

copy_children_preserving_unrelated() {
local source_dir="$1"
local target_dir="$2"
local source_path destination
mkdir -p "$target_dir"
ensure_real_directory "$target_dir"

for source_path in "$source_dir"/*; do
[[ -e "$source_path" ]] || continue
Expand All @@ -154,6 +169,46 @@ copy_children_preserving_unrelated() {
done
}

copy_pack_docs() {
local docs_target="$1"
local schema_destination="$docs_target/review-finding-schema.md"
ensure_real_directory "$docs_target"
ensure_real_directory "$docs_target/solutions"
if [[ -L "$schema_destination" ]]; then
rm -f "$schema_destination"
fi
if [[ -e "$schema_destination" && ! -f "$schema_destination" ]]; then
echo "Refusing to replace non-file path: $schema_destination" >&2
exit 1
fi
install -m 0644 "$repo_root/docs/review-finding-schema.md" "$schema_destination"
copy_children_preserving_unrelated "$repo_root/docs/solutions" "$docs_target/solutions"
}

link_pack_docs() {
local docs_target="$1"
local destination source_path
ensure_real_directory "$docs_target"
ensure_real_directory "$docs_target/solutions"

destination="$docs_target/review-finding-schema.md"
if [[ -e "$destination" && ! -L "$destination" ]]; then
echo "Refusing to replace non-symlink path: $destination" >&2
exit 1
fi
ln -sfn "$repo_root/docs/review-finding-schema.md" "$destination"

for source_path in "$repo_root"/docs/solutions/*; do
[[ -e "$source_path" ]] || continue
destination="$docs_target/solutions/$(basename "$source_path")"
if [[ -e "$destination" && ! -L "$destination" ]]; then
echo "Refusing to replace non-symlink path: $destination" >&2
exit 1
fi
ln -sfn "$source_path" "$destination"
done
}
Comment thread
justin808 marked this conversation as resolved.

while [[ $# -gt 0 ]]; do
case "$1" in
--host)
Expand Down Expand Up @@ -201,11 +256,23 @@ host="${resolved%%:*}"
target="${resolved#*:}"

if [[ "$mode" = "copy" ]]; then
mkdir -p "$target/skills" "$target/workflows" "$target/bin"
ensure_real_directory "$target/skills"
ensure_real_directory "$target/workflows"
ensure_real_directory "$target/docs"
ensure_real_directory "$target/bin"
copy_children_preserving_unrelated "$repo_root/skills" "$target/skills"
copy_children_preserving_unrelated "$repo_root/workflows" "$target/workflows"
copy_pack_docs "$target/docs"
for helper in "${bin_helpers[@]}"; do
install -m 0755 "$repo_root/bin/$helper" "$target/bin/$helper"
destination="$target/bin/$helper"
if [[ -L "$destination" ]]; then
rm -f "$destination"
fi
if [[ -e "$destination" && ! -f "$destination" ]]; then
echo "Refusing to replace non-file path: $destination" >&2
exit 1
fi
install -m 0755 "$repo_root/bin/$helper" "$destination"
done
else
mkdir -p "$target/skills" "$target/bin"
Expand All @@ -224,6 +291,7 @@ else
done
rm -f "$target/workflows"
ln -sfn "$repo_root/workflows" "$target/workflows"
link_pack_docs "$target/docs"
for helper in "${bin_helpers[@]}"; do
destination="$target/bin/$helper"
if [[ -e "$destination" && ! -L "$destination" ]]; then
Expand Down
65 changes: 64 additions & 1 deletion bin/install-agent-workflows-test.bash
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ test_codex_host_install_writes_helpers_and_metadata() {
assert_file "$target/skills/pr-batch/SKILL.md"
assert_file "$target/skills/pr-batch/agents/openai.yaml"
assert_file "$target/workflows/pr-processing.md"
assert_file "$target/docs/review-finding-schema.md"
assert_file "$target/docs/solutions/README.md"
assert_file "$target/bin/agent-workflow-seam-doctor"
assert_file "$target/bin/agent-workflows-status"
assert_file "$target/bin/agent-workflows-trust-audit"
Expand Down Expand Up @@ -133,6 +135,8 @@ test_claude_host_install_uses_claude_home_when_target_is_omitted() {
assert_file "$tmp/.claude/skills/pr-batch/SKILL.md"
assert_file "$tmp/.claude/skills/pr-batch/agents/openai.yaml"
assert_file "$tmp/.claude/workflows/pr-processing.md"
assert_file "$tmp/.claude/docs/review-finding-schema.md"
assert_file "$tmp/.claude/docs/solutions/README.md"
assert_file "$tmp/.claude/bin/agent-workflows-status"
assert_file "$tmp/.claude/bin/agent-workflows-trust-audit"
[[ ! -e "$tmp/.claude/.codex-plugin/plugin.json" ]] || fail "Codex native plugin manifest must not be installed into Claude home metadata"
Expand All @@ -142,33 +146,89 @@ test_copy_mode_preserves_unrelated_agent_files() {
local tmp target
tmp="$(mktemp -d)"
target="$tmp/codex-home"
mkdir -p "$target/skills/personal" "$target/workflows" "$target/bin"
mkdir -p "$target/skills/personal" "$target/workflows" "$target/docs" "$target/bin"
printf 'personal skill\n' > "$target/skills/personal/SKILL.md"
printf 'personal workflow\n' > "$target/workflows/personal.md"
printf 'personal docs\n' > "$target/docs/personal.md"
printf '#!/usr/bin/env bash\n' > "$target/bin/personal-helper"

"$ROOT/bin/install-agent-workflows" --host codex --target "$target" >/tmp/install-agent-workflows-test.out

assert_file "$target/skills/personal/SKILL.md"
assert_file "$target/workflows/personal.md"
assert_file "$target/docs/personal.md"
assert_file "$target/docs/review-finding-schema.md"
assert_file "$target/docs/solutions/README.md"
assert_file "$target/bin/personal-helper"
assert_file "$target/skills/pr-batch/SKILL.md"
}

test_copy_mode_does_not_replace_generic_consumer_docs() {
local tmp target
tmp="$(mktemp -d)"
target="$tmp/codex-home"
mkdir -p "$target/docs/adr"
printf 'consumer adoption docs\n' > "$target/docs/adoption.md"
printf 'consumer architecture decision\n' > "$target/docs/adr/0001-consumer.md"

"$ROOT/bin/install-agent-workflows" --host codex --target "$target" >/tmp/install-agent-workflows-test.out

grep -q 'consumer adoption docs' "$target/docs/adoption.md" || fail "copy mode replaced consumer docs/adoption.md"
grep -q 'consumer architecture decision' "$target/docs/adr/0001-consumer.md" || fail "copy mode replaced consumer docs/adr"
assert_file "$target/docs/review-finding-schema.md"
assert_file "$target/docs/solutions/README.md"
}

test_symlink_mode_links_skills_workflows_and_helpers() {
local tmp target
tmp="$(mktemp -d)"
target="$tmp/codex-home"
mkdir -p "$target/docs"
printf 'personal docs\n' > "$target/docs/personal.md"

"$ROOT/bin/install-agent-workflows" --host codex --target "$target" --mode symlink >/tmp/install-agent-workflows-test.out

assert_symlink "$target/skills/pr-batch"
assert_symlink "$target/workflows"
assert_file "$target/docs/personal.md"
assert_symlink "$target/docs/review-finding-schema.md"
[[ -d "$target/docs/solutions" && ! -L "$target/docs/solutions" ]] || fail "expected real docs/solutions directory"
assert_symlink "$target/docs/solutions/README.md"
assert_symlink "$target/bin/agent-workflow-seam-doctor"
assert_symlink "$target/bin/agent-workflows-trust-audit"
assert_file "$target/.agent-workflows-install.json"
}

test_symlink_mode_replaces_docs_directory_symlink() {
local tmp target external_docs
tmp="$(mktemp -d)"
target="$tmp/codex-home"
external_docs="$tmp/external-docs"
mkdir -p "$target" "$external_docs"
ln -s "$external_docs" "$target/docs"

"$ROOT/bin/install-agent-workflows" --host codex --target "$target" --mode symlink >/tmp/install-agent-workflows-test.out

[[ -d "$target/docs" && ! -L "$target/docs" ]] || fail "expected real docs directory"
assert_symlink "$target/docs/review-finding-schema.md"
[[ ! -e "$external_docs/review-finding-schema.md" ]] || fail "should not write through pre-existing docs symlink"
}

test_copy_mode_after_symlink_mode_does_not_delete_source_docs() {
local tmp target source_doc
tmp="$(mktemp -d)"
target="$tmp/codex-home"
source_doc="$ROOT/docs/solutions/README.md"

"$ROOT/bin/install-agent-workflows" --host codex --target "$target" --mode symlink >/tmp/install-agent-workflows-test.out
assert_symlink "$target/docs/solutions/README.md"
"$ROOT/bin/install-agent-workflows" --host codex --target "$target" >/tmp/install-agent-workflows-test.out

assert_file "$source_doc"
assert_file "$target/docs/solutions/README.md"
[[ ! -L "$target/docs/solutions/README.md" ]] || fail "copy mode should replace pack doc symlink with a real copy"
}

test_status_reports_not_installed_and_check_failed_explicitly() {
local tmp target output status
tmp="$(mktemp -d)"
Expand Down Expand Up @@ -321,7 +381,10 @@ main() {
test_installed_prompt_guard_ignores_unowned_docs
test_claude_host_install_uses_claude_home_when_target_is_omitted
test_copy_mode_preserves_unrelated_agent_files
test_copy_mode_does_not_replace_generic_consumer_docs
test_symlink_mode_links_skills_workflows_and_helpers
test_symlink_mode_replaces_docs_directory_symlink
test_copy_mode_after_symlink_mode_does_not_delete_source_docs
test_status_reports_not_installed_and_check_failed_explicitly
test_status_reports_upgrade_available_between_source_commits
test_upgrade_reinstalls_new_source_revision
Expand Down
10 changes: 10 additions & 0 deletions bin/validate
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@ ruby bin/agent-workflows-trust-audit-test.rb
echo "== push-downstream unit tests =="
ruby bin/push-downstream-test.rb

echo "== solution docs =="
ruby bin/validate-solutions-test.rb
ruby bin/validate-solutions

echo "== review finding schema =="
ruby bin/validate-review-findings-test.rb
ruby bin/validate-review-findings

echo "== installer/status/upgrade tests =="
bash bin/install-agent-workflows-test.bash

Expand All @@ -71,6 +79,7 @@ echo "== downstream registry dry-run =="
bin/push-downstream --config downstream.yml >/dev/null

echo "== helper tests =="
ruby skills/autoreview/bin/autoreview-target-state-test.rb
ruby skills/address-review/bin/fetch-pr-review-data-test.rb
ruby skills/plan-pr-batch/bin/pr-file-touch-map-test.rb
AGENT_WORKFLOWS_SOURCE_CHECKOUT=1 ruby skills/plan-pr-batch/scripts/check_goal_prompt_size.rb
Expand All @@ -81,6 +90,7 @@ ruby skills/pr-batch/bin/goal-completion-contract-test.rb
ruby skills/pr-batch/bin/pr-ci-readiness-test.rb
ruby skills/pr-batch/bin/agent-coord-bounded-test.rb
ruby skills/pr-batch/bin/pr-security-preflight-test.rb
ruby skills/task-observer/bin/task-observer-test.rb
ruby skills/update-changelog/bin/changelog-merged-prs-test.rb

echo "== rubocop ${RUBOCOP_VERSION} =="
Expand Down
Loading
Loading