@andyqiu/codeforge 0.5.14 → 0.5.15

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/bin/codeforge.mjs CHANGED
@@ -115,7 +115,7 @@ function installOpencode({ scope, dryRun, extraArgs, quiet = false }) {
115
115
  if (dryRun) flagArgs.push("--dry-run")
116
116
  }
117
117
  const all = [...baseArgs, ...flagArgs, ...(extraArgs ?? [])]
118
- log(`opencode: ${cmd} ${all.join(" ")}`)
118
+ if (!quiet) log(`opencode: ${cmd} ${all.join(" ")}`)
119
119
  const r = spawnSync(cmd, all, { stdio: quiet ? "pipe" : "inherit", cwd: REPO_ROOT })
120
120
  if (quiet && r.status !== 0) {
121
121
  if (r.stderr) process.stderr.write(r.stderr)
package/dist/index.js CHANGED
@@ -13269,8 +13269,8 @@ async function mergeSessionBack(opts) {
13269
13269
  });
13270
13270
  throw new Error(`mergeSessionBack: squash merge 失败(已 reset 主仓兜底): ${err.message}`);
13271
13271
  }
13272
- const hasDevOnce = await packageHasScript(mainRoot, "dev:once");
13273
- if (hasDevOnce) {
13272
+ const buildScript = await getBuildScript(mainRoot);
13273
+ if (buildScript) {
13274
13274
  const stagedRaw = await runGit2(mainRoot, [
13275
13275
  "diff",
13276
13276
  "--cached",
@@ -13281,18 +13281,18 @@ async function mergeSessionBack(opts) {
13281
13281
  const canSkipDevOnce = await shouldSkipDevOnce(mainRoot, stagedPaths);
13282
13282
  if (canSkipDevOnce) {
13283
13283
  const sourceCount = stagedPaths.filter((p) => /^(plugins|lib|src)\//.test(p) && !/\.(md|test\.ts)$/.test(p)).length;
13284
- console.log(`[session-worktree] skip dev:once: dist 已是最新(${sourceCount} staged 源文件 mtime <= dist mtime)`);
13284
+ console.log(`[session-worktree] skip ${buildScript}: dist 已是最新(${sourceCount} staged 源文件 mtime <= dist mtime)`);
13285
13285
  } else {
13286
13286
  try {
13287
- await runCmd("npm", ["run", "dev:once"], mainRoot);
13287
+ await runCmd("npm", ["run", buildScript], mainRoot);
13288
13288
  } catch (err) {
13289
13289
  await runGit2(mainRoot, ["reset", "--hard", "HEAD"]).catch(() => {});
13290
13290
  const msg = err instanceof Error ? err.message : String(err);
13291
- throw new Error(`dev:once 失败已 reset 主仓: ${msg}`);
13291
+ throw new Error(`${buildScript} 失败已 reset 主仓: ${msg}`);
13292
13292
  }
13293
13293
  }
13294
13294
  } else {
13295
- console.log(`[session-worktree] skip dev:once: not configured in ${mainRoot}/package.json`);
13295
+ console.warn(`[session-worktree] skip build step: neither build:dev nor dev:once configured in ${mainRoot}/package.json`);
13296
13296
  }
13297
13297
  const squashedRaw = await runGit2(wt, ["log", "--format=%s", `${baseSha}..HEAD`]);
13298
13298
  const squashedCommits = squashedRaw.split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
@@ -13430,6 +13430,13 @@ async function packageHasScript(mainRoot, scriptName) {
13430
13430
  return false;
13431
13431
  }
13432
13432
  }
13433
+ async function getBuildScript(mainRoot) {
13434
+ if (await packageHasScript(mainRoot, "build:dev"))
13435
+ return "build:dev";
13436
+ if (await packageHasScript(mainRoot, "dev:once"))
13437
+ return "dev:once";
13438
+ return null;
13439
+ }
13433
13440
  async function shouldSkipDevOnce(mainRoot, stagedPaths) {
13434
13441
  let distMtimeSec;
13435
13442
  try {
@@ -21355,9 +21362,9 @@ var RISK_PATTERNS = [
21355
21362
  },
21356
21363
  {
21357
21364
  tag: "write_secrets",
21358
- kinds: ["bash"],
21359
- re: /(\.env(?:\.\w+)?|id_[edr]sa|\.ssh\/id_|\.pem|\.p12|secret\.json)/i,
21360
- matchOn: ["command"]
21365
+ kinds: ["bash", "edit"],
21366
+ re: /(?:^|[\s/"'])(id_[edr]sa|secret\.json|\.env(?:\.\w+)?)(?:$|[\s"'/])|[\w./-]+\.(?:pem|p12)(?:$|[\s"'])|\.ssh\/id_/i,
21367
+ matchOn: ["command", "filePath", "path", "target"]
21361
21368
  },
21362
21369
  {
21363
21370
  tag: "write_etc",
@@ -21778,7 +21785,7 @@ import * as zlib from "node:zlib";
21778
21785
  // lib/version-injected.ts
21779
21786
  function getInjectedVersion() {
21780
21787
  try {
21781
- const v = "0.5.14";
21788
+ const v = "0.5.15";
21782
21789
  if (typeof v === "string" && /^\d+\.\d+\.\d+/.test(v)) {
21783
21790
  return v;
21784
21791
  }
@@ -23058,14 +23065,18 @@ var handler24 = workflowEngineServer;
23058
23065
  import path27 from "node:path";
23059
23066
  var PLUGIN_NAME25 = "session-worktree-guard";
23060
23067
  logLifecycle(PLUGIN_NAME25, "import", {});
23061
- var WRITE_INTENT_RE = />(?![=&])|\btee\b|\brm\b|\bmv\b|\bcp\b|\bmkdir\b|\btouch\b|\bchmod\b|\bchown\b|\bln\b/;
23062
- var READ_ONLY_COMMANDS = /^\s*(?:ls|cat|head|tail|grep|rg|find|fd|wc|stat|file|which|whereis|echo|pwd|cd|pushd|popd|env|printenv|type|less|more|sort|uniq|awk|tr|cut|jq|date|whoami|id|uname|git(?:\s+-C\s+\S+)?\s+(?:log|show|diff|status|branch|tag|remote|config\s+--get|rev-parse|rev-list|ls-files|ls-tree|cat-file|describe|reflog|blame|shortlog|name-rev|symbolic-ref|merge-base|worktree\s+list|stash\s+list|stash\s+show))\b/;
23063
- var SIDE_EFFECT_TOKEN_RE = />(?![=&])|\|\s*tee\b|\btee\b/;
23068
+ var WRITE_INTENT_RE = />(?![=&])(?!\s*\/dev\/(?:null|stdout|stderr|fd\/\d+)\b)|\btee\b|\brm\b|\bmv\b|\bcp\b|\bmkdir\b|\btouch\b|\bchmod\b|\bchown\b|\bln\b/;
23069
+ var READ_ONLY_COMMANDS = /^\s*(?:ls|cat|head|tail|grep|rg|find|fd|wc|stat|file|which|whereis|echo|pwd|cd|pushd|popd|env|printenv|type|less|more|sort|uniq|awk|tr|cut|jq|date|whoami|id|uname|node|npx|tsc|diff|python3?|git(?:\s+-C\s+\S+)?\s+(?:log|show|diff|status|branch|tag|remote|config\s+--get|rev-parse|rev-list|ls-files|ls-tree|cat-file|describe|reflog|blame|shortlog|name-rev|symbolic-ref|merge-base|worktree\s+list|stash\s+list|stash\s+show))\b/;
23070
+ var SIDE_EFFECT_TOKEN_RE = />(?![=&])(?!\s*\/dev\/(?:null|stdout|stderr|fd\/\d+)\b)|\|\s*tee\b|\btee\b/;
23064
23071
  function isReadOnlyBashCommand(command) {
23065
23072
  if (!READ_ONLY_COMMANDS.test(command))
23066
23073
  return false;
23067
23074
  if (SIDE_EFFECT_TOKEN_RE.test(command))
23068
23075
  return false;
23076
+ for (const re of INTERPRETER_WRITE_RES) {
23077
+ if (re.test(command))
23078
+ return false;
23079
+ }
23069
23080
  return true;
23070
23081
  }
23071
23082
  var INTERPRETER_WRITE_RES = [
@@ -23073,6 +23084,9 @@ var INTERPRETER_WRITE_RES = [
23073
23084
  /node.*writeFile/,
23074
23085
  /perl.*>/
23075
23086
  ];
23087
+ function stripCommitMessageArgs(command) {
23088
+ return command.replace(/(?:^|\s)(?:-m|--message|-F|--file)(?:=|\s+)("[^"]*"|'[^']*')/g, " ");
23089
+ }
23076
23090
  function escapeRegex2(s) {
23077
23091
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
23078
23092
  }
@@ -23161,13 +23175,14 @@ function commandContainsMainRootExcludingWorktree(command, mainRoot, worktreePat
23161
23175
  function detectBashWriteIntent(command, mainRoot) {
23162
23176
  if (isReadOnlyBashCommand(command))
23163
23177
  return false;
23164
- if (WRITE_INTENT_RE.test(command))
23178
+ const sanitized = stripCommitMessageArgs(command);
23179
+ if (WRITE_INTENT_RE.test(sanitized))
23165
23180
  return true;
23166
23181
  for (const re of INTERPRETER_WRITE_RES) {
23167
- if (re.test(command))
23182
+ if (re.test(sanitized))
23168
23183
  return true;
23169
23184
  }
23170
- if (buildGitVcsWriteRegex(mainRoot).test(command))
23185
+ if (buildGitVcsWriteRegex(mainRoot).test(sanitized))
23171
23186
  return true;
23172
23187
  return false;
23173
23188
  }
@@ -23181,13 +23196,14 @@ function isWriteOperation(toolName, argsObj, mainRoot) {
23181
23196
  return false;
23182
23197
  if (isReadOnlyBashCommand(command))
23183
23198
  return false;
23184
- if (WRITE_INTENT_RE.test(command))
23199
+ const sanitized = stripCommitMessageArgs(command);
23200
+ if (WRITE_INTENT_RE.test(sanitized))
23185
23201
  return true;
23186
23202
  for (const re of INTERPRETER_WRITE_RES) {
23187
- if (re.test(command))
23203
+ if (re.test(sanitized))
23188
23204
  return true;
23189
23205
  }
23190
- if (mainRoot && buildGitVcsWriteRegex(mainRoot).test(command))
23206
+ if (mainRoot && buildGitVcsWriteRegex(mainRoot).test(sanitized))
23191
23207
  return true;
23192
23208
  return false;
23193
23209
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@andyqiu/codeforge",
3
- "version": "0.5.14",
3
+ "version": "0.5.15",
4
4
  "description": "CodeForge — opencode 的零侵入扩展包",
5
5
  "type": "module",
6
6
  "private": false,
@@ -33,7 +33,7 @@
33
33
  "build:types": "tsc -p tsconfig.build.json --emitDeclarationOnly",
34
34
  "build:watch": "node ./scripts/build-with-version.mjs --watch",
35
35
  "dev": "node ./scripts/dev-sync.mjs --watch",
36
- "dev:once": "node ./scripts/dev-sync.mjs",
36
+ "build:dev": "node ./scripts/dev-sync.mjs",
37
37
  "dev-sync": "node ./scripts/dev-sync.mjs",
38
38
  "dev-sync:watch": "node ./scripts/dev-sync.mjs --watch",
39
39
  "typecheck": "tsc -p tsconfig.json --noEmit",
@@ -72,14 +72,9 @@
72
72
  "replay": "node ./scripts/codeforge-replay.mjs",
73
73
  "release": "node ./scripts/release.mjs",
74
74
  "release:dry": "node ./scripts/release.mjs --dry-run",
75
- "publish:patch": "bash ./scripts/publish.sh patch",
76
- "publish:minor": "bash ./scripts/publish.sh minor",
77
- "publish:major": "bash ./scripts/publish.sh major",
78
- "publish:dry": "bash ./scripts/publish.sh --dry-run",
79
- "publish:win:patch": "powershell -NoProfile -ExecutionPolicy Bypass -File ./scripts/publish.ps1",
80
- "publish:win:minor": "powershell -NoProfile -ExecutionPolicy Bypass -File ./scripts/publish.ps1 -Minor",
81
- "publish:win:major": "powershell -NoProfile -ExecutionPolicy Bypass -File ./scripts/publish.ps1 -Major",
82
- "publish:win:dry": "powershell -NoProfile -ExecutionPolicy Bypass -File ./scripts/publish.ps1 -DryRun",
75
+ "release:patch": "node ./scripts/release.mjs patch",
76
+ "release:minor": "node ./scripts/release.mjs minor",
77
+ "release:major": "node ./scripts/release.mjs major",
83
78
  "prepublishOnly": "npm run build && npm run typecheck && npm test",
84
79
  "prepare": "husky"
85
80
  },