@lazyingart/agintiflow 0.20.89 → 0.20.91

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lazyingart/agintiflow",
3
- "version": "0.20.89",
3
+ "version": "0.20.91",
4
4
  "type": "module",
5
5
  "description": "Low-cost, project-aware Web and CLI agents with DeepSeek/Venice/OpenAI routing, visible tool calls, durable sessions, scouts, AAPS, SCS, and guarded local execution.",
6
6
  "license": "Apache-2.0",
@@ -288,6 +288,18 @@ try {
288
288
  );
289
289
  assert(readonlyTestEchoPolicy.allowed, "read-only test/echo probe sequence should not require package-install-policy=allow");
290
290
  assert(readonlyTestEchoPolicy.category === "read-only", "read-only test/echo probe sequence should be classified as read-only");
291
+ const pdflatexCompilePolicy = evaluateCommandPolicy(
292
+ 'cd profile-latex-20260506 && pdflatex -interaction=nonstopmode -halt-on-error main.tex 2>&1; echo "PDFLATEX_EXIT:$?"',
293
+ dockerWorkspaceNoInstallsPolicy
294
+ );
295
+ assert(pdflatexCompilePolicy.allowed, "workspace-local pdflatex compile should be allowed without package installs");
296
+ assert(pdflatexCompilePolicy.category === "toolchain", "workspace-local pdflatex compile should be classified as toolchain");
297
+ const latexmkCompilePolicy = evaluateCommandPolicy(
298
+ 'cd profile-latex-20260506 && latexmk -pdf main.tex 2>&1; echo "LATEXMK_EXIT:$?"',
299
+ dockerWorkspaceNoInstallsPolicy
300
+ );
301
+ assert(latexmkCompilePolicy.allowed, "workspace-local latexmk compile should be allowed without package installs");
302
+ assert(latexmkCompilePolicy.category === "toolchain", "workspace-local latexmk compile should be classified as toolchain");
291
303
  const curlPolicy = evaluateCommandPolicy("curl -s -o /dev/null -w '%{http_code}' https://github.com/lazyingart/AgInTiFlow.git", dockerWorkspacePolicy);
292
304
  assert(curlPolicy.allowed, "curl URL probe with flags should be allowed in docker-workspace allow mode");
293
305
  assert(curlPolicy.needsNetwork, "curl URL probe with flags was not classified as network");
@@ -318,6 +330,18 @@ try {
318
330
  assert(cdWorkspacePolicy.allowed, "cd /workspace should be allowed in docker-workspace mode");
319
331
  const gitCleanDryRunPolicy = evaluateCommandPolicy("git clean -nd reports", dockerWorkspacePolicy);
320
332
  assert(gitCleanDryRunPolicy.allowed, "git clean dry-run should be allowed as read-only inspection evidence");
333
+ const localGitInitPolicy = evaluateCommandPolicy("git init", dockerWorkspaceNoInstallsPolicy);
334
+ assert(localGitInitPolicy.allowed, "local git init should be allowed without package installs");
335
+ assert(localGitInitPolicy.category === "git-workflow", "local git init should be classified as git-workflow");
336
+ const localGitCommitPolicy = evaluateCommandPolicy('git commit -m "Initial local workflow commit"', dockerWorkspaceNoInstallsPolicy);
337
+ assert(localGitCommitPolicy.allowed, "local git commit should be allowed without package installs");
338
+ assert(localGitCommitPolicy.category === "git-workflow", "local git commit should be classified as git-workflow");
339
+ const localGitSwitchPolicy = evaluateCommandPolicy("git switch -c feature-a", dockerWorkspaceNoInstallsPolicy);
340
+ assert(localGitSwitchPolicy.allowed, "local git switch -c should be allowed without package installs");
341
+ const localGitMergePolicy = evaluateCommandPolicy("git merge --ff-only feature-a", dockerWorkspaceNoInstallsPolicy);
342
+ assert(localGitMergePolicy.allowed, "local git fast-forward merge should be allowed without package installs");
343
+ const unsafeRebasePolicy = evaluateCommandPolicy("git rebase main", dockerWorkspaceNoInstallsPolicy);
344
+ assert(!unsafeRebasePolicy.allowed, "git rebase should still require stronger permission because it rewrites history");
321
345
  const unsafeCloneTarget = evaluateCommandPolicy("git clone https://github.com/lazyingart/AgInTiFlow.git ../AgInTiFlow", dockerWorkspacePolicy);
322
346
  assert(!unsafeCloneTarget.allowed, "git clone outside the workspace should be blocked");
323
347
  const blockedClonePolicy = evaluateCommandPolicy("git clone https://github.com/lazyingart/AgInTiFlow.git", {
@@ -750,6 +774,10 @@ try {
750
774
  "command_policy_readonly_probe_sequence_no_installs",
751
775
  "command_policy_readonly_version_pipeline_no_installs",
752
776
  "command_policy_readonly_test_echo_no_installs",
777
+ "command_policy_pdflatex_compile_no_installs",
778
+ "command_policy_latexmk_compile_no_installs",
779
+ "command_policy_local_git_workflow_no_installs",
780
+ "command_policy_git_rebase_still_guarded",
753
781
  "command_policy_git_clone_network",
754
782
  "command_policy_safe_chmod_sequence",
755
783
  "command_policy_cd_workspace",
@@ -20,4 +20,6 @@ tools:
20
20
 
21
21
  Always inspect `git status --short` and relevant diffs before committing or pushing. Keep commits scoped and stop on conflicts, divergence, or unrelated dirty work.
22
22
 
23
+ For local workflow practice or repository setup, prefer a disposable subdirectory if the user did not clearly target the current repository. Configure only local git identity (`git config user.name`, `git config user.email`) inside that repo; never change global git config. Use accurate git scenarios: a fast-forward merge means the target branch has not diverged; a non-fast-forward merge intentionally creates a merge commit after both branches diverge; a rebase rewrites local branch commits and should be used only in an explicitly disposable/local branch or after user approval.
24
+
23
25
  Use `gh` for PR/release/status workflows when authenticated. Fold long command output but preserve key errors, URLs, branch names, and commit hashes.
@@ -71,8 +71,19 @@ const NETWORK_FETCH_PATTERNS = [
71
71
  ];
72
72
 
73
73
  const GIT_WORKFLOW_PATTERNS = [
74
+ /^git\s+init(?:\s+(?:\.|[-\w./]+))?$/,
75
+ /^git\s+config(?:\s+--local)?\s+user\.(?:name|email)\s+(['"])[^'"\n]{1,160}\1$/,
76
+ /^git\s+config(?:\s+--local)?\s+init\.defaultBranch\s+(?:main|master|trunk|develop)$/,
74
77
  /^git\s+add(?:\s+[-\w./*]+)+$/,
75
- /^git\s+commit\s+(?:-a\s+)?-m\s+(['"])[^'"\n]{1,220}\1$/,
78
+ /^git\s+add\s+-A$/,
79
+ /^git\s+commit\s+(?:(?:-a|--allow-empty)\s+)*-m\s+(['"])[^'"\n]{1,220}\1$/,
80
+ /^git\s+branch\s+-M\s+[A-Za-z0-9][-\w./]*$/,
81
+ /^git\s+branch\s+[A-Za-z0-9][-\w./]*$/,
82
+ /^git\s+switch\s+(?:-c\s+)?[A-Za-z0-9][-\w./]*$/,
83
+ /^git\s+checkout\s+-b\s+[A-Za-z0-9][-\w./]*$/,
84
+ /^git\s+merge\s+--ff-only\s+[A-Za-z0-9][-\w./]*$/,
85
+ /^git\s+merge\s+--no-ff\s+--no-edit\s+[A-Za-z0-9][-\w./]*$/,
86
+ /^git\s+merge\s+[A-Za-z0-9][-\w./]*\s+--no-ff\s+--no-edit$/,
76
87
  /^git\s+fetch(?:\s+[-\w./:=]+)*$/,
77
88
  /^git\s+pull\s+--ff-only(?:\s+[-\w./:=]+)*$/,
78
89
  /^git\s+push(?:\s+[-\w./:=]+)*$/,
@@ -264,8 +275,23 @@ function classifyGitClone(normalized) {
264
275
  };
265
276
  }
266
277
 
278
+ function classifyGitWorkflow(normalized) {
279
+ if (!matchAny(GIT_WORKFLOW_PATTERNS, normalized)) return null;
280
+ const remote = /^git\s+(fetch|pull|push)\b/.test(normalized);
281
+ const writesWorkspace = !/^git\s+fetch\b/.test(normalized);
282
+ return {
283
+ category: remote ? "git-remote" : "git-workflow",
284
+ needsNetwork: remote,
285
+ writesWorkspace,
286
+ reason:
287
+ remote
288
+ ? "Git remote workflow command. Agent should inspect status/diff first and stop on divergence or conflicts."
289
+ : "Local git workflow command. Agent should inspect status/diff first and stop on conflicts or unrelated dirty work.",
290
+ };
291
+ }
292
+
267
293
  function classifySimpleCommand(normalized) {
268
- const readOnlyCommand = stripBenignRedirections(normalized);
294
+ const benignRedirectCommand = stripBenignRedirections(normalized);
269
295
  if (ALWAYS_BLOCKED_PATTERNS.some((pattern) => pattern.test(normalized))) {
270
296
  return { category: "blocked", reason: "Command is blocked because it may expose secrets or publish packages." };
271
297
  }
@@ -274,6 +300,8 @@ function classifySimpleCommand(normalized) {
274
300
  }
275
301
  const gitCleanDryRun = classifyGitCleanDryRun(normalized);
276
302
  if (gitCleanDryRun) return gitCleanDryRun;
303
+ const gitWorkflowClassification = classifyGitWorkflow(normalized);
304
+ if (gitWorkflowClassification) return gitWorkflowClassification;
277
305
  if (matchAny(UNSAFE_GIT_PATTERNS, normalized)) {
278
306
  return {
279
307
  category: "destructive",
@@ -305,20 +333,10 @@ function classifySimpleCommand(normalized) {
305
333
  reason: `Command changes workspace file mode: ${normalized}`,
306
334
  };
307
335
  }
308
- if (matchAny(GIT_WORKFLOW_PATTERNS, normalized)) {
309
- const remote = /^git\s+(fetch|pull|push)\b/.test(normalized);
310
- const writesWorkspace = /^git\s+(add|commit|pull)\b/.test(normalized);
311
- return {
312
- category: remote ? "git-remote" : "git-workflow",
313
- needsNetwork: remote,
314
- writesWorkspace,
315
- reason: "Git workflow command. Agent should run git status/diff first and stop on conflicts or divergence.",
316
- };
317
- }
318
336
  const gitCloneClassification = classifyGitClone(normalized);
319
337
  if (gitCloneClassification) return gitCloneClassification;
320
338
 
321
- const unquoted = stripQuotedSegments(readOnlyCommand);
339
+ const unquoted = stripQuotedSegments(benignRedirectCommand);
322
340
  const lowered = ` ${unquoted.toLowerCase()} `;
323
341
  if (BLOCKED_WRITE_TOKENS.some((part) => lowered.includes(part))) {
324
342
  return {
@@ -337,25 +355,25 @@ function classifySimpleCommand(normalized) {
337
355
  };
338
356
  }
339
357
 
340
- if (matchAny(READ_ONLY_PATTERNS, readOnlyCommand) || isReadOnlyFindCommand(normalized)) {
358
+ if (matchAny(READ_ONLY_PATTERNS, benignRedirectCommand) || isReadOnlyFindCommand(normalized)) {
341
359
  return { category: "read-only", needsNetwork: false, writesWorkspace: false };
342
360
  }
343
- if (matchAny(TEST_PATTERNS, normalized)) {
361
+ if (matchAny(TEST_PATTERNS, benignRedirectCommand)) {
344
362
  return { category: "test", needsNetwork: false, writesWorkspace: false };
345
363
  }
346
- if (matchAny(TOOLCHAIN_PATTERNS, normalized)) {
364
+ if (matchAny(TOOLCHAIN_PATTERNS, benignRedirectCommand)) {
347
365
  return { category: "toolchain", needsNetwork: false, writesWorkspace: true };
348
366
  }
349
- if (matchAny(NETWORK_FETCH_PATTERNS, normalized)) {
350
- return { category: "network-fetch", needsNetwork: true, writesWorkspace: /(\s-o\s|\s-O\s)/.test(normalized) };
367
+ if (matchAny(NETWORK_FETCH_PATTERNS, benignRedirectCommand)) {
368
+ return { category: "network-fetch", needsNetwork: true, writesWorkspace: /(\s-o\s|\s-O\s)/.test(benignRedirectCommand) };
351
369
  }
352
- if (matchAny(SYSTEM_PACKAGE_INSTALL_PATTERNS, normalized)) {
370
+ if (matchAny(SYSTEM_PACKAGE_INSTALL_PATTERNS, benignRedirectCommand)) {
353
371
  return { category: "system-package-install", needsNetwork: true, writesWorkspace: false, requiresDockerRoot: true };
354
372
  }
355
- if (matchAny(PACKAGE_INSTALL_PATTERNS, normalized)) {
373
+ if (matchAny(PACKAGE_INSTALL_PATTERNS, benignRedirectCommand)) {
356
374
  return { category: "package-install", needsNetwork: true, writesWorkspace: true };
357
375
  }
358
- if (matchAny(ENV_SETUP_PATTERNS, normalized)) {
376
+ if (matchAny(ENV_SETUP_PATTERNS, benignRedirectCommand)) {
359
377
  return { category: "env-setup", needsNetwork: false, writesWorkspace: true };
360
378
  }
361
379
 
@@ -255,7 +255,7 @@ export const TASK_PROFILES = {
255
255
  id: "github",
256
256
  label: "GitHub maintenance",
257
257
  prompt:
258
- "Bias toward safe git and GitHub maintenance while still fixing code/docs when asked. Always inspect git status and remotes first, separate unrelated changes, run relevant checks before commits, use gh when available for PR/issues/releases, prefer fast-forward pulls, and stop on conflicts or ambiguous history.",
258
+ "Bias toward safe git and GitHub maintenance while still fixing code/docs when asked. Always inspect git status and remotes first, separate unrelated changes, run relevant checks before commits, use gh when available for PR/issues/releases, prefer fast-forward pulls, and stop on conflicts or ambiguous history. For local workflow practice, use a disposable subdirectory, set only local git identity, avoid real remotes unless explicitly requested, and describe fast-forward, non-fast-forward merge, and rebase evidence accurately.",
259
259
  tools: ["shell", "files", "web_search", "inspect_project"],
260
260
  },
261
261
  word: {