Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
21 changes: 21 additions & 0 deletions BACKLOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ CC-001/CC-002 were consumed by PR #24 fix bundle inline, with no standalone entr
| CC-484 | ✅ done | JapanJob 與 qa-testing-rules 的 `pmctl context` refresh 未生效:重現 session/index/update/pack 實際路徑、repo-root/project-key/DB freshness,補跨 repo live E2E 與 actionable diagnostics | ops/memory | 2026-07-13 | feedback:2026-07-13 | P1 | retrieval |
| CC-485 | ✅ done | 工具能力與維護者政策分離:通用 gate/test/PM 不規定使用流程;affected feedback 僅屬開發/PR,pm-dispatch release 固定由 `release-verify.sh --e2e`(內含 fresh full suite)+ checklist 驗收 | arch/process | 2026-07-13 | pr:#398 | P3 | design |
| CC-486 | ⏸ deferred | direct-impact test planner mapping 提前退出:changed path 含 `agents/*.md`/`commands/*.md` 時 `map_path` 呼叫未註冊的 `lint-frontmatter`,`add_suite` 回傳 1 並在 `set -e` 下無輸出終止,導致 `run-tests.sh --base ... --list` exit 1 | ops/test | 2026-07-13 | feedback:2026-07-13 | P2 | hygiene |
| CC-487 | 🔵 active | GitHub Actions `test-guards` 非確定性掛起:逐 case breadcrumb + bounded background writer/wait + orphan cleanup,避免 main CI 無輸出佔用 runner 近一小時 | ops/test | 2026-07-14 | feedback:2026-07-14 | P1 | hygiene |
| CC-465 | 🔵 active | memory/context 關鍵詞管線 CJK 支援:抽出共用零依賴斷詞 lib,取代三處各自 ASCII-only 抽詞;工作序列起點(465→467→468→466)(2026-07-07 記憶系統深入分析) | memory | 2026-07-07 | feedback:2026-07-07 | P2 | retrieval |
| CC-466 | 🔵 active | 記憶卡片生命週期閉環:expires_at 執行 + 關窗式 supersede + usage sidecar 休眠偵測 + doctor→distill 接線;排在 CC-467 之後(需其遙測為前置)(2026-07-07 記憶系統分析 + 外部研究 Graphiti/mcp-memory-service) | memory | 2026-07-07 | feedback:2026-07-07 | P2 | retrieval |
| CC-467 | 🔵 active | `pmctl memory stats`:注入效益可視化(唯讀聚合器)——注入 bytes/卡片命中分佈/從未命中卡/episode 填寫率,回答「記憶有跟沒有差在哪」;排在 CC-466 之前(2026-07-07;業界僅離線 recall 評測,無 per-injection 遙測) | DX/memory | 2026-07-07 | — | P2 | retrieval |
Expand Down Expand Up @@ -654,6 +655,26 @@ _Terminal_ (CC-378: swept OUT to `BACKLOG-ARCHIVE.md` by `scripts/archive-closed

---

## CC-487 — GitHub Actions `test-guards` 非確定性掛起與 bounded diagnostics 🔵 active

**Problem**: main SHA `0b66f1f` 的 GitHub Actions run `29298816362` 中,`test-guards` job 從 2026-07-14 01:32:51Z 執行至 02:30:38Z,停留在 `== guard-inject-memory ==` 後沒有更多輸出,最後由使用者手動取消。runner cleanup 記錄兩個殘留 `bash` process。該區段不只包含 inject hook,亦包含 `memory-usage/concurrent-no-lost-updates` 與 `memory-usage/contention-matrix-flock-and-mkdir-fallback` 等背景 writer/`wait` 測試;CI 未啟用逐 case breadcrumb,現有 artifact 無法確定是哪一個 case 或 process 未收斂。

**Boundary**: 目前不能把這次取消判定為 canonical-memory 產品 regression。相同程式碼在乾淨 HOME 的本機完整 `scripts/test-guards.sh` 為 296/296,inject/context 範圍 50/50;contention matrix 連跑 12 次、concurrent update 連跑 20 次均通過。這是一張獨立 repo-wide CI hardening 票,不混入 CC-483、CC-486 或 maintainer workflow 內容。

**Requirement**:
1. GitHub Actions 的直接 `test-guards` job 必須輸出 `RUNNING test-guards/<case>`,取消或逾時時能從 log 唯一定位 active case。
2. 對含背景 writer/FIFO/`wait` 的 guard concurrency cases 加 case-level deadline、TERM→KILL 與 `EXIT` cleanup;任一 writer 失敗或未退出時輸出 backend、round、writer id、PID、lock state 與已完成計數,不得無界等待。
3. 對直接 CI job 加整體上限,且上限必須大於正常完整 suite 的合理波動、遠小於 57 分鐘;timeout 必須保留最後 case breadcrumb 與診斷,而非只留下 group heading。
4. 使用接近 GitHub `ubuntu-24.04` runner 的乾淨 HOME/PATH 重跑完整 suite 與 contention stress;不得靠放寬正確性斷言、降低 writer 數或跳過 mkdir fallback 來讓測試變綠。

**Acceptance**: (a) 正常 CI `test-guards` 完整通過;(b) 人工注入一個不退出 writer 時,在 bounded deadline 內非零結束、指出精確 case/writer 並清除所有 child process;(c) 不再可能讓單一 guard case 無輸出佔用 runner 近一小時;(d) focused contention stress、完整 `scripts/test-guards.sh`、`scripts/test-run-all-tests.sh` 與 `git diff --check` 全綠。

**Evidence**: GitHub Actions run `29298816362`, job `86978053691`;本機乾淨環境完整 296/296 通過,故根因仍需以新增 breadcrumb/bounded diagnostics 捕捉,不能從單次取消紀錄過度推論。

**Dependencies**: 承接 [[CC-477]] 已完成的 lock protocol 與 runner breadcrumbs;本票只處理仍存在的 CI hang 可診斷性與 bounded lifecycle。

---

## CC-484 — JapanJob/qa-testing-rules pmctl context refresh 失效 ✅ 2026-07-13

**Problem**: JapanJob 的 session 與 qa-testing-rules 實際工作流沒有順利用 `pmctl context` 刷新內容。[[CC-455]] 曾修正 context plane 預設 repo root 跟隨 caller CWD,但目前 live 行為仍可能在 repo-root resolution、worktree/project key、context.db 位置、mtime skip、session hook/prepare wiring 或 update/query 順序其中一層失效;只看 unit test 不能確認是哪一層。
Expand Down
25 changes: 21 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,19 @@ chore(cc-###): short summary

Before opening a PR:

1. Run `/pr-gate` in the main thread.
2. Address any required review blocks.
3. Confirm the final checklist in your PR description.
The authoritative maintainer sequence and failure loop are defined in
[`/ship` Steps 2.5–3.5](commands/ship.md#step-25--refactorreuse-audit).

1. Use affected tests during implementation, then complete `/ship` Step 2.5's
refactor/reuse audit.
2. Run `/pr-gate` in the main thread.
3. Address findings and apply `/ship` Step 3's conditional recheck rule.
4. After GO, complete `/ship` Step 3.5's authoritative full-suite check.
5. Confirm the final checklist in your PR description.

[`/pr-gate` skill](commands/pr-gate.md) is the hard-gate review entry point and is documented alongside the same execution patterns in [`docs/dispatch-brief.md`](docs/dispatch-brief.md).
The refactor/reuse checkpoint is this repository's maintainer policy; it does
not make `pmctl gate` or its component tools mandatory for downstream users.

## PM brief schema and contracts

Expand All @@ -59,12 +67,21 @@ If this repository adds changes to the dispatch pipeline, update this schema fir

## Testing and validation

For every file-writing or schema-affecting PR, run the full test suite:
During implementation and gate-fix iteration, run only the affected suites:

```bash
bash scripts/run-tests.sh --base <base-ref>
```

After PR-gate returns GO, run the full test suite once against the final tree:

```bash
bash scripts/run-all-tests.sh
```

For full-suite failures and re-gating, follow the authoritative loop in
[`/ship` Step 3.5](commands/ship.md#step-35--authoritative-full-suite).

This runs all suites (hooks, install, portable, pr-gate, usage, pm-scripts, etc.) and
prints a pass/fail/skip summary. For a focused run on one suite, invoke it directly,
for example `bash scripts/test-guards.sh` or `bash scripts/test-install.sh`. Use
Expand Down
1 change: 1 addition & 0 deletions agents/project-pm.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ Record the split decision in project memory and surface it to the user. Never le
3. **`--targeted` re-run**: Once the fix is committed, re-run gate with `--targeted <reviewer,...>` (maps to `--reviewers` at the script level). Full tier is for first round and scope-unclear situations only.
4. **Minimum-list principle**: Gate round N's findings are the minimum set to fix, not a complete enumeration. In the fix brief, instruct Codex to "grep for all similar patterns in the same scope and fix them proactively" — this prevents the next round from finding the same class of issue in an adjacent location.
5. **Next-layer sweep**: After each fix, ask "does this fix reveal a deeper layer of the same class of issue?" Common triggers: fixed a missing test → are there adjacent untested behaviors in the same feature? Fixed a doc mismatch → are there other mismatches in the same file? Fixed a contract violation → does the contract have other clauses not yet tested? This check costs one minute and prevents one gate round.
6. **Refactor/reuse recheck threshold**: Apply `commands/ship.md` Step 3's structural-versus-localized threshold. Emit `refactor_reuse_recheck: required` for structural or scope-unclear remediation; emit `refactor_reuse_recheck: skip` plus a one-line reason for localized fixes that preserve the architecture. A required recheck runs before the targeted gate; if it changes the diff, rerun affected focused tests first.

## Executor selection

Expand Down
31 changes: 28 additions & 3 deletions commands/pr-gate.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,21 +59,29 @@ call is still available.

### Executor routing is passed by flag only

Choose the gate executor/model using the authoritative
[gate model diversity policy](../docs/review-model.md#gate-model-diversity).
Resolve actual model identities rather than inferring them from host or adapter
names. Replace `<gate_executor>` below with the selected literal value and pass
`--model <gate_model>` when the route default is not the selected model.

This command should pass exactly one of these explicit modes when known:

- `--executor codex` for codex route (or when `command -v codex` is true and user explicitly requested)
- `--executor claude` for claude-only path
- `--executor auto` for default behavior (`command -v codex` decides)

`--executor auto` is the default; keep that shape here for parity with existing
`/pm` profile defaults and `scripts/install-guards.sh` auto-detect.
`--executor auto` remains the compatibility fallback only when the
implementation model or alternate executor availability cannot be determined.

```bash
RAW_ARGS="${ARGUMENTS:-}"
TIER_OVERRIDE=""
TARGETED_REVIEWERS=""
SCOPE_TOKENS=()
PARALLEL=false
GATE_EXECUTOR="<gate_executor>"
GATE_MODEL=""

if [[ -n "$RAW_ARGS" ]]; then
read -r -a TOKENS <<< "$RAW_ARGS"
Expand Down Expand Up @@ -105,13 +113,29 @@ while [[ "$idx" -lt "${#TOKENS[@]}" ]]; do
--parallel)
PARALLEL=true
;;
--executor)
idx=$((idx + 1))
GATE_EXECUTOR="${TOKENS[$idx]:-}"
;;
--model)
idx=$((idx + 1))
GATE_MODEL="${TOKENS[$idx]:-}"
[[ -n "$GATE_MODEL" ]] || { echo "error: --model requires a value" >&2; exit 2; }
;;
*)
SCOPE_TOKENS+=("$tok")
;;
esac
idx=$((idx + 1))
done

# Validate after parsing so this also rejects a missing substitution of the
# <gate_executor> default, not only an invalid explicit --executor value.
case "$GATE_EXECUTOR" in
codex|claude|auto) ;;
*) echo "error: gate executor must resolve to codex, claude, or auto" >&2; exit 2 ;;
esac

SCOPE="${SCOPE_TOKENS[*]:-}"
# --cd's value below, "<work_dir>", is a placeholder to replace with the
# actual working directory (already known from context) as a literal quoted
Expand All @@ -121,7 +145,8 @@ SCOPE="${SCOPE_TOKENS[*]:-}"
# `pmctl:*` prefix match. The quotes around the placeholder keep this block
# valid, executable Bash even before that substitution (bare, unquoted
# `<work_dir>` would be parsed as I/O redirection and fail to parse).
GATE_ARGS=(--cd "<work_dir>" --executor auto)
GATE_ARGS=(--cd "<work_dir>" --executor "$GATE_EXECUTOR")
[[ -n "$GATE_MODEL" ]] && GATE_ARGS+=(--model "$GATE_MODEL")
[[ -n "$TIER_OVERRIDE" ]] && GATE_ARGS+=(--tier "$TIER_OVERRIDE")
[[ -n "$TARGETED_REVIEWERS" ]] && GATE_ARGS+=(--reviewers "$TARGETED_REVIEWERS")
[[ -n "$SCOPE" ]] && GATE_ARGS+=(--scope "$SCOPE")
Expand Down
75 changes: 70 additions & 5 deletions commands/ship.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ description: Take one explicit backlog ticket from implementation through pr-gat
argument-hint: "<ticket-id>"
---

Run a single, explicitly named ticket end-to-end: implement → gate → fix → gate
→ open PR. This is the main-thread's own default operating discipline made
Run a single, explicitly named ticket end-to-end: implement → affected tests →
refactor/reuse audit → gate → fix → conditional re-audit → gate → full suite →
open PR. This is the main-thread's own default operating discipline made
runnable as one command, not a new background/unattended supervisor — the
session stays open and you stay reachable the whole time.

Expand Down Expand Up @@ -97,9 +98,44 @@ implementation to codex/claude/opencode. `pmctl dispatch run` is not part of
this flow; the only executor dispatch in `/ship` is the gate's own reviewer
dispatch in Step 3.

Use `bash scripts/run-tests.sh --base <base-ref>` for implementation feedback.
Pass explicit `--path` or suite inputs when narrowing an iteration further.
Do not run `run-all-tests.sh` before the first PR gate: the affected-test
planner is the fast feedback path, while the authoritative full suite belongs
after a GO verdict.

## Step 2.5 — Refactor/reuse audit

After the primary implementation and its affected verification are complete,
run one maintainability audit on the actual diff **before the first PR gate**.
This is a pm-dispatch maintainer policy, not a prerequisite built into the
generic `pmctl gate` command.

1. **Simplify**: inspect changed production code for duplicated branches,
wrappers, parsing, locking, path handling, or indirection that can be made
smaller without changing behavior.
2. **Reuse**: use `rg` to inspect existing helpers, peer implementations, and
all call sites in the affected scope. Prefer a proven shared helper over a
second local implementation, but do not introduce speculative abstractions.
3. **Verify**: apply warranted behavior-preserving cleanup, rerun the affected
focused tests, and record either `CHANGED: <what was consolidated>` or
`PASS: no warranted refactor/reuse change` for the PR handoff.

This initial audit runs exactly once even when it finds no cleanup. It is not
delegated to PR-gate reviewers: doing the cheap maintainability pass first
keeps avoidable duplication and incidental complexity out of the expensive
cross-model review loop.

## Step 3 — Gate loop

Run `pmctl gate run --executor codex --cd "<work_dir>" --lifecycle foreground`
Choose `<gate_executor>` and, when needed, `<gate_model>` before the first gate
using the authoritative [gate model diversity policy](../docs/review-model.md#gate-model-diversity).
Base the choice on actual model identities, record both identities in the
handoff, and keep the same resolved pair for targeted re-runs. Add
`--model "<gate_model>"` below only when the executor default does not already
resolve to the selected gate model.

Run `pmctl gate run --executor <gate_executor> --cd "<work_dir>" --lifecycle foreground`
(substitute `<work_dir>` with the literal absolute working directory, not
`"$PWD"` — a shell-variable expansion makes the command unanalyzable
statically and forces a manual approval every time even though a bare
Expand All @@ -117,13 +153,26 @@ uses to keep the main thread free for other work; run `foreground` and read
the resulting `Final: GO|NO-GO` verdict directly from the gate result file
once the call returns.

- **GO** → go to Step 4.
- **GO** → go to Step 3.5.
- **NO-GO** → invoke the `project-pm` agent to synthesize the gate result
against the verdict table and Rules A/B in `agents/project-pm.md` (source-first
read of every cited diff file, discovery sweep of all call sites of a
flagged helper, minimum-list is a floor not a ceiling). Fix **every** finding
it returns — high, medium, and low, hard gate and advisory alike, not only
the blocking ones. Re-run `pmctl gate run --executor codex --cd "<work_dir>"
the blocking ones.

Before re-running the gate, classify the remediation:

- **Re-run the refactor/reuse audit** when the fix changes a shared helper or
public interface, schema, ownership, data flow, layer boundary, introduces
or removes an abstraction, moves logic across files, performs cross-file
deduplication, raises `architecture_impact`, or leaves the structural scope
unclear. Rerun affected focused tests if the audit changes the diff.
- **Skip the re-audit with a recorded reason** for localized corrections that
preserve the established structure, such as wording/comments, a narrow
assertion or fixture adjustment, or a small guard/error-handling fix.

Then re-run `pmctl gate run --executor <gate_executor> --cd "<work_dir>"
--lifecycle foreground --reviewers <reviewer,...>` (same literal-path
substitution as Step 3's first call — never `"$PWD"`; the `/pr-gate`
`--targeted` flag maps to this same `--reviewers` option) for the reviewers
Expand All @@ -143,6 +192,18 @@ once the call returns.

Any other NO-GO, at any round count, gets fixed and re-gated without asking.

## Step 3.5 — Authoritative full suite

Only after PR-gate returns GO, run `bash scripts/run-all-tests.sh` once and
verify its authoritative result artifact. This is the final repo-wide
regression check, not an iteration tool.

If the full suite finds a diff-caused failure, fix it, rerun affected tests,
apply the same refactor/reuse recheck threshold, and return to the targeted
gate path for every reviewer territory the fix touched. After GO, run the full
suite again against the new tree. Keep pre-existing or infrastructure failures
separate; do not silently attach unrelated repairs to the ticket.

## Step 4 — Open the PR

```bash
Expand All @@ -152,9 +213,13 @@ gh pr create --title "<type>(<ticket-id>): <short summary>" --body "$(cat <<'EOF
- <one-line summary of the change>

## Gate
- Refactor/reuse audit: <CHANGED summary | PASS no change>
- Implementation model: <model id/family>
- Review executor/model: <executor + resolved model id/family>
- Rounds: <N>
- Final verdict: GO
- Result file: <path from the last /pr-gate relay>
- Full suite: <passed count and authoritative result artifact>

Ticket: <ticket-id>
EOF
Expand Down
Loading