@kylecheng3146/agent-ops 0.8.5 → 0.8.6

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.
@@ -637,8 +637,8 @@ export function parseArgs(argv) {
637
637
  throw new CliArgumentError("CLI_OPTION_NOT_ALLOWED", "--target-version may be used only with update.");
638
638
  }
639
639
  if (base !== undefined && command !== "verify" && command !== "review" &&
640
- command !== "batch" && !(command === "task" && action === "complete")) {
641
- throw new CliArgumentError("CLI_OPTION_NOT_ALLOWED", "--base may be used only with verify, review, batch or task complete.");
640
+ command !== "batch" && !(command === "task" && (action === "complete" || action === "debug"))) {
641
+ throw new CliArgumentError("CLI_OPTION_NOT_ALLOWED", "--base may be used only with verify, review, batch, task complete or task debug.");
642
642
  }
643
643
  if ((parentBase !== undefined || width !== undefined) && command !== "batch") {
644
644
  throw new CliArgumentError("CLI_OPTION_NOT_ALLOWED", `${parentBase !== undefined ? "--parent-base" : "--width"} may be used only with batch.`);
@@ -196,7 +196,7 @@ Options:
196
196
  --task <id> status, attach, revise, replan, pin-finding, complete, archive, export, advance
197
197
  --session <id> create, attach, status, advance, debug
198
198
  --evidence <criterion-id=reference> complete, repeatable
199
- --base <git-ref> complete: a clean committed range
199
+ --base <git-ref> complete, debug: a clean committed range
200
200
  --yes advance: authorize the two review sessions
201
201
  --json
202
202
 
@@ -3,6 +3,10 @@ import { sha256 } from "../fs/hash.js";
3
3
  import { AgentOpsError } from "../fs/paths.js";
4
4
  import { RunControlService } from "./controls.js";
5
5
  const plain = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
6
+ const MAX_SCOPE = 32 * 1024;
7
+ /** A large Write or patch is still one observation: keep its identity by digest, never block the run on its size. */
8
+ const bounded = (scope) => scope.length <= MAX_SCOPE ? scope :
9
+ canonicalJson({ truncated: true, length: scope.length, sha256: sha256(scope), head: scope.slice(0, 4096) });
6
10
  /** Provider decisions are observations, never an alternate permission executor. */
7
11
  export async function recordNativeRunAuthorization(repository, event) {
8
12
  if (!plain(event.payload))
@@ -51,10 +55,10 @@ export async function recordNativeRunAuthorization(repository, event) {
51
55
  if (event.host === "codex" && payload.threadId !== worker.nativeJobId)
52
56
  throw new AgentOpsError("RUN_AUTHORIZATION_STALE", "Native approval belongs to another thread.");
53
57
  const service = new RunControlService(repository);
54
- for (const decision of decisions)
58
+ for (const { command, resource, ...decision } of decisions)
55
59
  await service.recordAuthorization(event.runId, { ...decision,
56
- authorizationId: decision.id, workerId: worker.workerId, generation: worker.generation, nativeSessionId: worker.nativeSessionId,
57
- source: event.host === "codex" ? "codex-auto-review" : "claude-auto-mode", commandDigest: sha256(decision.command),
58
- resourceDigest: sha256(decision.resource), policyConfigHash: state.policyBinding.configHash,
60
+ command: bounded(command), resource: bounded(resource), authorizationId: decision.id, workerId: worker.workerId, generation: worker.generation, nativeSessionId: worker.nativeSessionId,
61
+ source: event.host === "codex" ? "codex-auto-review" : "claude-auto-mode", commandDigest: sha256(bounded(command)),
62
+ resourceDigest: sha256(bounded(resource)), policyConfigHash: state.policyBinding.configHash,
59
63
  runtimeHash: state.policyBinding.runtimeHash, policyArtifactDigest: state.policyBinding.artifactDigest, expiresAt: state.policyBinding.expiresAt });
60
64
  }
@@ -2,6 +2,9 @@
2
2
  export function isDebugIssue(prompt) {
3
3
  if (prompt.length === 0 || prompt.length > 64 * 1024 || prompt.includes("\0"))
4
4
  return false;
5
+ // Harness-injected turns (subagent hand-backs, task notifications) are not a human report.
6
+ if (/^\s*<(?:agent-message|task-notification|teammate-message)\b/u.test(prompt))
7
+ return false;
5
8
  const value = prompt.normalize("NFKC").toLowerCase();
6
9
  if (/\b(?:explain|describe|what is|how does|refactor|feature|implement|design)\b|說明|解释|解釋|重構|新增功能|設計|實作功能/u.test(value))
7
10
  return false;
@@ -38,7 +38,8 @@ function codexUserText(row) {
38
38
  return undefined;
39
39
  }
40
40
  /** Host transcripts are the user-event authority; CLI actor/text fields are never accepted. */
41
- export async function readDebugUserEvent(root, sessionId, home = homedir(), kind = "latest") {
41
+ /** `worktreeRoot` is the session's owned worktree: Claude stamps each row with the shell's cwd, which moves there after `cd`. */
42
+ export async function readDebugUserEvent(root, sessionId, home = homedir(), kind = "latest", worktreeRoot) {
42
43
  if (!/^[a-f0-9-]{36}$/u.test(sessionId))
43
44
  throw new AgentOpsError("TASK_DEBUG_GRANT_UNSUPPORTED", "This host has no identifiable native user-event source.");
44
45
  const canonicalHome = await realpath(home).catch(() => home);
@@ -77,7 +78,8 @@ export async function readDebugUserEvent(root, sessionId, home = homedir(), kind
77
78
  for (let index = rows.length - 1; index >= 0; index--) {
78
79
  const row = rows[index];
79
80
  const text = codexSource ? codexUserText(row) :
80
- row?.type === "user" && row.sessionId === sessionId && row.cwd === root && row.message?.role === "user" ? row.message.content : undefined;
81
+ row?.type === "user" && row.sessionId === sessionId && (row.cwd === root || (worktreeRoot !== undefined && row.cwd === worktreeRoot)) && row.message?.role === "user" &&
82
+ row.isMeta !== true && (row.origin === undefined || row.origin?.kind === "human") ? row.message.content : undefined;
81
83
  if (typeof text !== "string" || text.length > 64 * 1024 || (kind === "control" && debugUserControl(text) === null))
82
84
  continue;
83
85
  const timestamp = Date.parse(row.timestamp);
@@ -248,7 +248,7 @@ export class DebugService {
248
248
  const record = await readWorktreeRecord(this.options.root);
249
249
  const origin = record?.mainRoot ?? this.options.root;
250
250
  try {
251
- return await readDebugUserEvent(origin, sessionId, home, kind);
251
+ return await readDebugUserEvent(origin, sessionId, home, kind, origin === this.options.root ? undefined : this.options.root);
252
252
  }
253
253
  catch (error) {
254
254
  if (origin === this.options.root || !(error instanceof AgentOpsError) || error.code !== "TASK_DEBUG_GRANT_UNSUPPORTED")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kylecheng3146/agent-ops",
3
- "version": "0.8.5",
3
+ "version": "0.8.6",
4
4
  "description": "Evidence-driven development loops for agy, Codex, Claude Code, and opencode",
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN LICENSE",