agent-afk 5.235.0 → 5.236.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,18 @@
1
+ import type { ExecFn } from './gh.js';
2
+ export declare const FIX_OF_FIX_WINDOW_DAYS = 7;
3
+ export declare const FIX_OF_FIX_LABEL = "fix-of-fix";
4
+ export declare function extractReferencedPrNumbers(text: string): number[];
5
+ export declare function getPrMergedAt(prNumber: number, execFn?: ExecFn): Promise<string | null>;
6
+ export declare function isMergedWithinDays(mergedAt: string, withinDays: number, now?: Date): boolean;
7
+ export declare function ensureFixOfFixLabel(execFn?: ExecFn): Promise<void>;
8
+ export declare function applyFixOfFixLabel(prNumber: number | string, execFn?: ExecFn): Promise<void>;
9
+ export interface FixOfFixResult {
10
+ isFixOfFix: boolean;
11
+ recentlyMergedRefs: number[];
12
+ allRefs: number[];
13
+ }
14
+ export declare function detectAndLabelFixOfFix(currentPrNumber: number | string, prBodyOrTitle: string, opts?: {
15
+ execFn?: ExecFn;
16
+ now?: Date;
17
+ windowDays?: number;
18
+ }): Promise<FixOfFixResult>;
@@ -66,6 +66,31 @@ Return: relevant facts with 1-line summaries, **plus the stores actually consult
66
66
 
67
67
  Read `SPINE.md` from the repo root (same directory as `AFK.md`). If the file does not exist or is empty, skip silently -- do not mention it in the snapshot. If it exists and has entries, extract its invariant (INV-*), rejected-pattern (REJ-*), and taste entries (TST-*) and include them in the snapshot so architectural constraints are visible before proposing changes.
68
68
 
69
+ ### Eval-pipeline recency survey *(bash — software domain only)*
70
+
71
+ For software-domain sessions, check whether the eval-run pipeline is current. This guard catches silent regressions that accumulate when the pipeline goes unrun during high-velocity sprints.
72
+
73
+ Run:
74
+ ```
75
+ tail -1 ~/.afk/agent-framework/improve/eval-runs/.index.jsonl 2>/dev/null
76
+ ```
77
+
78
+ Parse the `timestamp` field from the output. Then compute the age in days relative to today's date.
79
+
80
+ **Threshold**: Read `AFK_EVAL_STALENESS_DAYS` from the environment (default: 7). If the env var is `0`, skip this check silently.
81
+
82
+ **Surface as a warning finding when any of these are true:**
83
+ - The index file does not exist → `⚠ Eval-pipeline has NEVER run. Run \`afk improve eval-run\` to establish a baseline.`
84
+ - The file exists but the timestamp is absent or unparseable → `⚠ Eval-pipeline recency guard: index unreadable.`
85
+ - Age in days ≥ threshold → `⚠ Eval-pipeline is STALE: last eval-run was N days ago (exceeds AFK_EVAL_STALENESS_DAYS=N threshold). Run \`afk improve eval-run\`.`
86
+
87
+ Skip this check silently when:
88
+ - Domain is not `software`, OR
89
+ - Working directory has no `package.json` / `pyproject.toml` / `Cargo.toml` / `go.mod` at root level (heuristic that this is not a software project), OR
90
+ - `AFK_EVAL_STALENESS_DAYS=0`.
91
+
92
+ Include the result (fresh or warning) in the Implementation risks line of the snapshot.
93
+
69
94
  ## Synthesis
70
95
 
71
96
  Assemble the survey results into a ground-truth snapshot (6 lines minimum, 7 when SPINE.md has entries):
@@ -74,7 +99,7 @@ Assemble the survey results into a ground-truth snapshot (6 lines minimum, 7 whe
74
99
  - Infrastructure: CI present? package scripts? authoritative configs for this task
75
100
  - Memory hits: facts (1-line each) + which stores were consulted, or `none (consulted: …)`
76
101
  - Spine constraints *(only when SPINE.md exists with entries)*: INV-*, REJ-*, TST-* entries. Omit this line entirely when SPINE.md is absent or empty.
77
- - Implementation risks: e.g. "branch is `main`, don't edit directly"; "CI runs on push"; "memory says prior attempt used approach X"
102
+ - Implementation risks: e.g. "branch is `main`, don't edit directly"; "CI runs on push"; "memory says prior attempt used approach X"; include any eval-pipeline staleness warning here.
78
103
  - Epistemic confidence: `<high|medium|low>` — based on how much state could be verified. Flag if working directory is sparse, if domain is unfamiliar, or if key artifacts may be missing.
79
104
 
80
105
  Surface the snapshot and stop. The orchestrator then uses these verified facts — not assumptions — to decide the next step. This skill never edits files.
@@ -124,6 +124,40 @@ gh pr create \
124
124
 
125
125
  PR bodies are markdown: they routinely carry backticks (inline code), `$(...)`, and quotes. **Never** inline the body as `--body "$(cat <<'EOF' … EOF)"` — the shell parses backticks/`$(` inside the command substitution before `gh` ever runs, so the call fails (or worse, opens the PR with a truncated/garbled body and you don't notice). `--body-file` reads the file verbatim: no shell quoting, no escaping. Only `--title` stays inline — keep it a single plain line with no backticks.
126
126
 
127
+ **Phase 8b — Fix-of-fix detection (runs immediately after the PR URL is returned by Phase 8).**
128
+ Scan the PR title and body for cross-references to other PRs. If any referenced PR was merged within the last 7 days, apply the `fix-of-fix` label and record a structured metadata block.
129
+
130
+ ```
131
+ # 1. Extract referenced PR numbers from the PR body using the patterns:
132
+ # #NNNN, fix(#NNNN), regression from #N, follow-up to #N, addresses #N,
133
+ # fixes/closes/resolves #N
134
+ #
135
+ # 2. For each referenced PR number (excluding the current PR):
136
+ gh pr view <N> --json mergedAt --jq .mergedAt
137
+ # If mergedAt is non-null and within 7 days → it qualifies.
138
+ #
139
+ # 3. If any qualify:
140
+ gh label create fix-of-fix \
141
+ --description "PR that fixes a bug introduced by a recently-merged PR (merged within 7 days)" \
142
+ --color D93F0B --force
143
+ gh pr edit <current-PR-number> --add-label fix-of-fix
144
+ #
145
+ # 4. Append a machine-readable cross-reference section to the PR body:
146
+ gh pr edit <current-PR-number> --body-file <updated-body-file>
147
+ ```
148
+
149
+ Structured metadata to append (only when fix-of-fix is detected):
150
+
151
+ ```markdown
152
+ ## Cross-references
153
+
154
+ <!-- fix-of-fix: true -->
155
+ <!-- referenced-prs: <N1>, <N2>, ... -->
156
+ Recently-merged PRs referenced by this fix: #N1, #N2, …
157
+ ```
158
+
159
+ **Skip gracefully** when `gh` is unavailable or any step fails — the PR is already open and that is the deliverable. Never abort Phase 8b failure back to the user as a blocking error; log a one-line note instead (e.g. `fix-of-fix detection skipped: <reason>`).
160
+
127
161
  **Phase 9 — Reclaim the worktree.**
128
162
  Skip entirely unless the work you just shipped lives under `.afk-worktrees/` (check the invocation cwd from Phase 1 — if the path has no `.afk-worktrees/` segment, there is nothing to reclaim; go straight to the PR URL).
129
163
 
@@ -14,7 +14,7 @@ export declare function installSignalHandlers(deps: SignalHandlerDeps): {
14
14
  removeListeners: () => void;
15
15
  };
16
16
  export declare function printExitSummary(ctx: InteractiveCtx, worktreeHandle: WorktreeHandle | undefined, saveCurrentSession: () => string | undefined): void;
17
- export declare function snapshotGitStateForCancelAll(cwd: string): void;
17
+ export declare function snapshotGitStateForCancelAll(cwd: string): Promise<void>;
18
18
  export declare function makeSessionSaver(ctx: InteractiveCtx): {
19
19
  saveCurrentSession: () => string | undefined;
20
20
  isSaved: () => boolean;