@mmerterden/multi-agent-pipeline 16.18.0 → 16.19.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.
- package/CHANGELOG.md +45 -0
- package/README.md +5 -5
- package/README.tr.md +2 -2
- package/docs/FIGMA_PIPELINE.md +1 -1
- package/docs/adr/0001-three-model-triage.md +4 -2
- package/docs/architecture.md +2 -2
- package/docs/ecosystem.md +13 -11
- package/docs/features.md +2 -2
- package/index.js +1 -1
- package/install/_common.mjs +25 -1
- package/install/_dev-only-files.mjs +2 -2
- package/install/_mcp-register.mjs +4 -3
- package/install/_plugin-skills.mjs +1 -3
- package/install/copilot.mjs +18 -9
- package/install/index.mjs +2 -4
- package/install/templates/copilot-instructions.md +7 -7
- package/package.json +1 -1
- package/pipeline/claude-md-template.md +2 -2
- package/pipeline/commands/multi-agent/SKILL.md +5 -5
- package/pipeline/commands/multi-agent/complaint-analysis/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/design-check/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/help/SKILL.md +2 -2
- package/pipeline/commands/multi-agent/local-autopilot/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/review/SKILL.md +27 -14
- package/pipeline/commands/multi-agent/review-analysis/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/store-ready/SKILL.md +2 -2
- package/pipeline/commands/multi-agent/sync/SKILL.md +2 -2
- package/pipeline/commands/sim-test.md +54 -15
- package/pipeline/lib/credential-inventory.sh +15 -2
- package/pipeline/lib/credential-store-resolver.sh +14 -4
- package/pipeline/lib/credential-store.sh +8 -2
- package/pipeline/lib/extract-conventions.sh +1 -14
- package/pipeline/lib/fetch-confluence.sh +12 -4
- package/pipeline/lib/fetch-crashlytics.sh +11 -8
- package/pipeline/lib/fetch-document.sh +1 -1
- package/pipeline/lib/fetch-figma-annotations.sh +7 -5
- package/pipeline/lib/fetch-fortify.sh +5 -3
- package/pipeline/lib/fetch-graylog.sh +5 -3
- package/pipeline/lib/figma-mcp-refresh.sh +1 -1
- package/pipeline/lib/figma-screenshot.sh +27 -24
- package/pipeline/lib/figma-token.sh +8 -4
- package/pipeline/lib/issue-fetcher.sh +0 -1
- package/pipeline/lib/jira-publish.sh +7 -5
- package/pipeline/lib/md2confluence-v3.py +13 -7
- package/pipeline/lib/multi-repo-pipeline.sh +18 -8
- package/pipeline/lib/plan-todos.sh +11 -0
- package/pipeline/lib/post-pr-review.sh +9 -2
- package/pipeline/lib/repo-cache.sh +18 -10
- package/pipeline/lib/review-watch.sh +60 -14
- package/pipeline/lib/shadow-git.sh +8 -4
- package/pipeline/lib/vercel-deploy.sh +2 -2
- package/pipeline/multi-agent-refs/_dev-context.md +5 -2
- package/pipeline/multi-agent-refs/analysis/locked.md +4 -4
- package/pipeline/multi-agent-refs/analysis/render.md +1 -1
- package/pipeline/multi-agent-refs/cross-cli-contract.md +1 -1
- package/pipeline/multi-agent-refs/outside-the-pipeline.md +6 -6
- package/pipeline/multi-agent-refs/phases/log-format.md +1 -1
- package/pipeline/multi-agent-refs/phases/modes.md +1 -1
- package/pipeline/multi-agent-refs/phases/phase-0-init.md +4 -2
- package/pipeline/multi-agent-refs/phases/phase-1-analysis.md +3 -3
- package/pipeline/multi-agent-refs/phases/phase-2-planning.md +5 -5
- package/pipeline/multi-agent-refs/phases/phase-4-review.md +21 -16
- package/pipeline/multi-agent-refs/tracker-contract.md +1 -1
- package/pipeline/rules/figma-pipeline.md +18 -72
- package/pipeline/rules/outside-the-pipeline.md +4 -3
- package/pipeline/schemas/agent-state.schema.json +1 -1
- package/pipeline/schemas/token-budget.json +1 -1
- package/pipeline/scripts/_stack-routing.mjs +1 -1
- package/pipeline/scripts/agent-guard.py +102 -21
- package/pipeline/scripts/anonymize-findings.mjs +7 -6
- package/pipeline/scripts/build-skills-index.mjs +14 -3
- package/pipeline/scripts/cost-budget-check.mjs +5 -3
- package/pipeline/scripts/cost-lib.sh +0 -15
- package/pipeline/scripts/diff-explain.mjs +22 -12
- package/pipeline/scripts/gc-refs.sh +6 -2
- package/pipeline/scripts/gc-tmp.sh +1 -1
- package/pipeline/scripts/gc-worktrees.sh +1 -1
- package/pipeline/scripts/gen-mode-dispatch.mjs +3 -3
- package/pipeline/scripts/github-ssh-setup.sh +7 -2
- package/pipeline/scripts/graph-build.mjs +2 -2
- package/pipeline/scripts/jira-wiki-escape.mjs +2 -1
- package/pipeline/scripts/keychain.py +12 -11
- package/pipeline/scripts/learning-curve.mjs +1 -1
- package/pipeline/scripts/migrate-prefs.mjs +1 -1
- package/pipeline/scripts/output-quality-check.sh +3 -1
- package/pipeline/scripts/phase-tracker.sh +1 -1
- package/pipeline/scripts/phase0-exit-gate.mjs +2 -1
- package/pipeline/scripts/plan-coverage-gate.mjs +2 -1
- package/pipeline/scripts/pre-commit-check.sh +23 -13
- package/pipeline/scripts/prune-logs.sh +1 -1
- package/pipeline/scripts/render-agent-log-cost.sh +3 -1
- package/pipeline/scripts/render-cost-summary.sh +4 -2
- package/pipeline/scripts/render-work-summary.sh +5 -3
- package/pipeline/scripts/repo-map.mjs +3 -2
- package/pipeline/scripts/scan-skills.sh +6 -2
- package/pipeline/scripts/search-logs.sh +8 -6
- package/pipeline/scripts/sign-skills.sh +3 -1
- package/pipeline/scripts/smoke-cross-cli-behavior.sh +1 -1
- package/pipeline/scripts/triage-memory.mjs +25 -4
- package/pipeline/scripts/uninstall.mjs +20 -12
- package/pipeline/scripts/update-check.sh +2 -2
- package/pipeline/scripts/update-issue-progress.sh +6 -5
- package/pipeline/scripts/validate-analysis-doc.mjs +6 -6
- package/pipeline/scripts/verify-skills.sh +3 -1
- package/pipeline/scripts/worktree-finalize.sh +22 -10
- package/pipeline/skills/.skill-manifest.json +81 -57
- package/pipeline/skills/.skills-index.json +19 -19
- package/pipeline/skills/shared/README.md +8 -8
- package/pipeline/skills/shared/core/multi-agent/SKILL.md +7 -7
- package/pipeline/skills/shared/core/multi-agent-design-check/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-help/SKILL.md +2 -2
- package/pipeline/skills/shared/core/multi-agent-local/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-local-autopilot/SKILL.md +2 -2
- package/pipeline/skills/shared/core/multi-agent-review/SKILL.md +23 -14
- package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +2 -2
- package/pipeline/skills/shared/external/NOTICE-dimillian-skills.md +56 -0
- package/pipeline/skills/shared/external/accessibility-compliance-accessibility-audit/SKILL.md +0 -4
- package/pipeline/skills/shared/external/api-patterns/SKILL.md +12 -24
- package/pipeline/skills/shared/external/app-store-changelog/references/release-notes-guidelines.md +34 -0
- package/pipeline/skills/shared/external/app-store-changelog/scripts/collect_release_changes.sh +33 -0
- package/pipeline/skills/shared/external/architecture/SKILL.md +7 -9
- package/pipeline/skills/shared/external/debugging-strategies/SKILL.md +0 -4
- package/pipeline/skills/shared/external/fastapi-pro/SKILL.md +0 -1
- package/pipeline/skills/shared/external/github-actions-templates/SKILL.md +0 -14
- package/pipeline/skills/shared/external/hig-components-content/SKILL.md +13 -13
- package/pipeline/skills/shared/external/hig-components-layout/SKILL.md +16 -16
- package/pipeline/skills/shared/external/hig-components-status/SKILL.md +6 -6
- package/pipeline/skills/shared/external/hig-components-system/SKILL.md +13 -13
- package/pipeline/skills/shared/external/hig-foundations/SKILL.md +23 -23
- package/pipeline/skills/shared/external/hig-inputs/SKILL.md +18 -18
- package/pipeline/skills/shared/external/hig-patterns/SKILL.md +30 -30
- package/pipeline/skills/shared/external/hig-platforms/SKILL.md +11 -11
- package/pipeline/skills/shared/external/hig-technologies/SKILL.md +33 -33
- package/pipeline/skills/shared/external/ios-coding-standard/references/STANDARD.md +52 -52
- package/pipeline/skills/shared/external/ios-coding-standard/references/lint-local.sh +1 -1
- package/pipeline/skills/shared/external/ios-coding-standard/references/rules.yml +11 -11
- package/pipeline/skills/shared/external/ios-developer/SKILL.md +0 -1
- package/pipeline/skills/shared/external/ios-module-structure/SKILL.md +7 -3
- package/pipeline/skills/shared/external/localization-reuse-map/SKILL.md +9 -15
- package/pipeline/skills/shared/external/macos-spm-app-packaging/SKILL.md +0 -5
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/bootstrap/Package.swift +17 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/bootstrap/Sources/MyApp/Resources/.keep +0 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/bootstrap/Sources/MyApp/main.swift +11 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/bootstrap/version.env +2 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/build_icon.sh +49 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/compile_and_run.sh +63 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/launch.sh +28 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/make_appcast.sh +82 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/package_app.sh +206 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/setup_dev_signing.sh +52 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/sign-and-notarize.sh +52 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/version.env +2 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/references/packaging.md +17 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/references/release.md +32 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/references/scaffold.md +79 -0
- package/pipeline/skills/shared/external/monorepo-architect/SKILL.md +0 -1
- package/pipeline/skills/shared/external/nodejs-backend-patterns/SKILL.md +0 -4
- package/pipeline/skills/shared/external/swift-concurrency-expert/references/approachable-concurrency.md +63 -0
- package/pipeline/skills/shared/external/swift-concurrency-expert/references/swift-6-2-concurrency.md +272 -0
- package/pipeline/skills/shared/external/swift-concurrency-expert/references/swiftui-concurrency-tour-wwdc.md +33 -0
- package/pipeline/skills/shared/external/swiftui-performance-audit/references/code-smells.md +150 -0
- package/pipeline/skills/shared/external/swiftui-performance-audit/references/demystify-swiftui-performance-wwdc23.md +46 -0
- package/pipeline/skills/shared/external/swiftui-performance-audit/references/optimizing-swiftui-performance-instruments.md +29 -0
- package/pipeline/skills/shared/external/swiftui-performance-audit/references/profiling-intake.md +44 -0
- package/pipeline/skills/shared/external/swiftui-performance-audit/references/report-template.md +47 -0
- package/pipeline/skills/shared/external/swiftui-performance-audit/references/understanding-hangs-in-your-app.md +33 -0
- package/pipeline/skills/shared/external/swiftui-performance-audit/references/understanding-improving-swiftui-performance.md +52 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/app-wiring.md +201 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/async-state.md +96 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/components-index.md +46 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/controls.md +57 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/deeplinks.md +66 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/focus.md +90 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/form.md +97 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/grids.md +71 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/haptics.md +71 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/input-toolbar.md +51 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/lightweight-clients.md +93 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/list.md +86 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/loading-placeholders.md +38 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/macos-settings.md +71 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/matched-transitions.md +59 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/media.md +73 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/menu-bar.md +101 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/navigationstack.md +159 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/overlay.md +45 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/performance.md +62 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/previews.md +48 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/scroll-reveal.md +133 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/scrollview.md +87 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/searchable.md +71 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/sheets.md +155 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/split-views.md +72 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/tabview.md +114 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/theming.md +71 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/title-menus.md +93 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/top-bar.md +49 -0
- package/pipeline/skills/shared/external/swiftui-view-refactor/references/mv-patterns.md +161 -0
- package/pipeline/skills/skills-index.md +8 -8
- package/pipeline/skills/shared/external/help-skills/SKILL.md +0 -166
|
@@ -57,11 +57,22 @@ function parseFrontmatter(raw) {
|
|
|
57
57
|
if (end < 0) return {};
|
|
58
58
|
const body = raw.slice(3, end).trim();
|
|
59
59
|
const out = {};
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
const lines = body.split("\n");
|
|
61
|
+
for (let i = 0; i < lines.length; i++) {
|
|
62
|
+
const m = lines[i].match(/^([\w-]+):\s*(.*)$/);
|
|
62
63
|
if (!m) continue;
|
|
63
64
|
let value = m[2].trim();
|
|
64
|
-
if (
|
|
65
|
+
if (/^[|>][+-]?$/.test(value)) {
|
|
66
|
+
// YAML block scalar: the text is the indented lines that follow, and the
|
|
67
|
+
// indicator itself is not a description.
|
|
68
|
+
const parts = [];
|
|
69
|
+
while (i + 1 < lines.length && (/^\s/.test(lines[i + 1]) || lines[i + 1].trim() === "")) {
|
|
70
|
+
parts.push(lines[++i].trim());
|
|
71
|
+
}
|
|
72
|
+
value = parts.join(" ").replace(/\s+/g, " ").trim();
|
|
73
|
+
} else if (value.startsWith('"') && value.endsWith('"')) {
|
|
74
|
+
value = value.slice(1, -1);
|
|
75
|
+
}
|
|
65
76
|
out[m[1]] = value;
|
|
66
77
|
}
|
|
67
78
|
return out;
|
|
@@ -13,12 +13,14 @@
|
|
|
13
13
|
* coding tool; this turns "will this burn my tokens?" into a visible number.
|
|
14
14
|
*
|
|
15
15
|
* Inputs (CLI overrides prefs):
|
|
16
|
-
* --task-id <id> Locate
|
|
16
|
+
* --task-id <id> Locate $HOME/.claude/logs/multi-agent/<id>/tracker-state.json
|
|
17
|
+
* (also tried: <id> without a leading #, task-<id>)
|
|
17
18
|
* --tracker <path> Explicit tracker JSON (skips lookup)
|
|
18
19
|
* --prefs <path> Preferences JSON; reads .global.costBudget
|
|
19
20
|
* --max-usd <n> Hard ceiling (USD)
|
|
20
21
|
* --warn-pct <n> Warn threshold as percent of max-usd (1..99)
|
|
21
|
-
* --pricing-model <m> opus | sonnet | haiku
|
|
22
|
+
* --pricing-model <m> fable | opus | sonnet | haiku (any key under cost-table.json
|
|
23
|
+
* prices; default fable, the most expensive tier)
|
|
22
24
|
* --enabled Force-enable even if prefs say otherwise
|
|
23
25
|
*
|
|
24
26
|
* Output: one human-readable status line on stdout.
|
|
@@ -62,7 +64,7 @@ for (let i = 0; i < argv.length; i++) {
|
|
|
62
64
|
if (flags.help || flags.h) {
|
|
63
65
|
process.stdout.write(
|
|
64
66
|
"Usage: cost-budget-check.mjs [--task-id <id> | --tracker <path>] [--prefs <path>]\n" +
|
|
65
|
-
" [--max-usd <n>] [--warn-pct <n>] [--pricing-model opus|sonnet|haiku] [--enabled]\n",
|
|
67
|
+
" [--max-usd <n>] [--warn-pct <n>] [--pricing-model fable|opus|sonnet|haiku] [--enabled]\n",
|
|
66
68
|
);
|
|
67
69
|
process.exit(0);
|
|
68
70
|
}
|
|
@@ -15,9 +15,6 @@
|
|
|
15
15
|
# absent). Returns null when $rate is null.
|
|
16
16
|
# cost_floor_cents($u)
|
|
17
17
|
# -> floor USD to whole cents; null passes through.
|
|
18
|
-
#
|
|
19
|
-
# cost_usd <rate-json> <tin> <tout> [tcached] - scalar convenience wrapper
|
|
20
|
-
# that prints the raw (unrounded) USD via jq. Prints nothing when jq is absent.
|
|
21
18
|
|
|
22
19
|
COST_JQ_DEFS='
|
|
23
20
|
def cost_usd_of($rate; $tin; $tout; $tcached):
|
|
@@ -29,15 +26,3 @@ COST_JQ_DEFS='
|
|
|
29
26
|
def cost_floor_cents($u):
|
|
30
27
|
if $u == null then null else (($u * 100) | floor) / 100 end;
|
|
31
28
|
'
|
|
32
|
-
|
|
33
|
-
cost_usd() {
|
|
34
|
-
local rate="$1" tin="$2" tout="$3" tcached="${4:-0}"
|
|
35
|
-
command -v jq >/dev/null 2>&1 || return 0
|
|
36
|
-
jq -n \
|
|
37
|
-
--argjson rate "$rate" \
|
|
38
|
-
--argjson tin "$tin" \
|
|
39
|
-
--argjson tout "$tout" \
|
|
40
|
-
--argjson tcached "$tcached" \
|
|
41
|
-
"$COST_JQ_DEFS"'
|
|
42
|
-
cost_usd_of($rate; $tin; $tout; $tcached)'
|
|
43
|
-
}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*
|
|
12
12
|
* Inputs (any one):
|
|
13
13
|
* --triage <path> Path to triage-output.json
|
|
14
|
-
* --task-id <#N|JIRA> Resolve
|
|
14
|
+
* --task-id <#N|JIRA> Resolve $HOME/.claude/logs/multi-agent/<id>/agent-state.json
|
|
15
15
|
* --state <path> Path to agent-state.json with embedded triage
|
|
16
16
|
*
|
|
17
17
|
* Diff source:
|
|
@@ -31,6 +31,8 @@
|
|
|
31
31
|
*/
|
|
32
32
|
|
|
33
33
|
import { readFileSync, existsSync } from "fs";
|
|
34
|
+
import { join } from "path";
|
|
35
|
+
import { homedir } from "os";
|
|
34
36
|
import { execFileSync } from "child_process";
|
|
35
37
|
|
|
36
38
|
const argv = process.argv.slice(2);
|
|
@@ -55,7 +57,7 @@ if (flags.help || flags.h) {
|
|
|
55
57
|
Inputs (one required):
|
|
56
58
|
--triage <path> Path to triage-output.json
|
|
57
59
|
--state <path> agent-state.json with embedded triage
|
|
58
|
-
--task-id <id> Look up
|
|
60
|
+
--task-id <id> Look up $HOME/.claude/logs/multi-agent/<id>/agent-state.json
|
|
59
61
|
|
|
60
62
|
Diff source:
|
|
61
63
|
--branch <name> Branch to diff (default: current)
|
|
@@ -68,24 +70,32 @@ Output:
|
|
|
68
70
|
process.exit(0);
|
|
69
71
|
}
|
|
70
72
|
|
|
73
|
+
function resolveStateByTaskId(id) {
|
|
74
|
+
const bare = String(id).replace(/^#/, "");
|
|
75
|
+
const logRoot = join(homedir(), ".claude", "logs", "multi-agent");
|
|
76
|
+
const candidates = [...new Set([String(id), bare, `task-${bare}`])].map((d) =>
|
|
77
|
+
join(logRoot, d, "agent-state.json"),
|
|
78
|
+
);
|
|
79
|
+
const found = candidates.find((p) => existsSync(p));
|
|
80
|
+
if (!found)
|
|
81
|
+
die(`no agent-state.json for task ${id} under ${logRoot} (tried ${candidates.join(", ")})`);
|
|
82
|
+
return found;
|
|
83
|
+
}
|
|
84
|
+
|
|
71
85
|
function loadTriage() {
|
|
72
86
|
if (flags.triage) {
|
|
73
87
|
if (!existsSync(flags.triage)) die(`triage file not found: ${flags.triage}`);
|
|
74
88
|
return JSON.parse(readFileSync(flags.triage, "utf-8"));
|
|
75
89
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
90
|
+
const statePath =
|
|
91
|
+
flags.state || (flags["task-id"] ? resolveStateByTaskId(flags["task-id"]) : null);
|
|
92
|
+
if (statePath) {
|
|
93
|
+
if (!existsSync(statePath)) die(`state file not found: ${statePath}`);
|
|
94
|
+
const state = JSON.parse(readFileSync(statePath, "utf-8"));
|
|
79
95
|
const triage = state?.phases?.["4"]?.triage ?? state?.triage;
|
|
80
|
-
if (!triage) die(`no triage block found in ${
|
|
96
|
+
if (!triage) die(`no triage block found in ${statePath}`);
|
|
81
97
|
return triage;
|
|
82
98
|
}
|
|
83
|
-
if (flags["task-id"]) {
|
|
84
|
-
die(
|
|
85
|
-
"--task-id resolution not implemented in this script - use --triage or --state directly. " +
|
|
86
|
-
"The slash command resolves task IDs via the orchestrator and passes --state to this script.",
|
|
87
|
-
);
|
|
88
|
-
}
|
|
89
99
|
die("one of --triage, --state, or --task-id is required");
|
|
90
100
|
}
|
|
91
101
|
|
|
@@ -111,8 +111,11 @@ if [ -z "$REFS_DIRS" ]; then
|
|
|
111
111
|
fi
|
|
112
112
|
|
|
113
113
|
# Match the node-id shape offload-ref.sh writes (p<phase>-<slug>-<8 hex>.md).
|
|
114
|
-
# Anything else in that directory belongs to someone else.
|
|
115
|
-
|
|
114
|
+
# Anything else in that directory belongs to someone else. The glob is a cheap
|
|
115
|
+
# pre-filter for find; the regex is the actual shape (a plain `p*-*-*.md`
|
|
116
|
+
# also matched pr-body-final.md).
|
|
117
|
+
NODE_GLOB='p[0-9]*-*-????????.md'
|
|
118
|
+
NODE_RE='^p[0-9][0-9a-z.]*-[a-z0-9-]+-[0-9a-f]{8}\.md$'
|
|
116
119
|
|
|
117
120
|
MATCHES=""
|
|
118
121
|
while IFS= read -r dir; do
|
|
@@ -128,6 +131,7 @@ while IFS= read -r dir; do
|
|
|
128
131
|
[ -n "$found" ] || continue
|
|
129
132
|
while IFS= read -r f; do
|
|
130
133
|
[ -n "$f" ] || continue
|
|
134
|
+
printf '%s\n' "$(basename "$f")" | grep -Eq "$NODE_RE" || continue
|
|
131
135
|
# Grace: skip anything touched inside the window.
|
|
132
136
|
if [ "$GRACE_MIN" -gt 0 ] && [ -n "$(find "$f" -mmin -"$GRACE_MIN" 2>/dev/null)" ]; then
|
|
133
137
|
continue
|
|
@@ -110,7 +110,7 @@ while IFS= read -r -d '' p; do
|
|
|
110
110
|
# Fresh-scratch grace: spare items an in-flight run touched recently
|
|
111
111
|
# (checks the item and, for dirs, anything inside it).
|
|
112
112
|
if [ "$GRACE_MIN" -gt 0 ] &&
|
|
113
|
-
find "$p" -mmin "-$GRACE_MIN" -print 2>/dev/null
|
|
113
|
+
[ -n "$(find "$p" -mmin "-$GRACE_MIN" -print -quit 2>/dev/null)" ]; then
|
|
114
114
|
skipped_active=$((skipped_active + 1))
|
|
115
115
|
continue
|
|
116
116
|
fi
|
|
@@ -108,7 +108,7 @@ EOF
|
|
|
108
108
|
if printf '%s\n' "$registered" | grep -qxF "$dir"; then
|
|
109
109
|
continue # healthy registered worktree - kill/finish territory
|
|
110
110
|
fi
|
|
111
|
-
if [ "$OLDER_MIN" -gt 0 ] && find "$dir" -type f -mmin "-$OLDER_MIN" 2>/dev/null
|
|
111
|
+
if [ "$OLDER_MIN" -gt 0 ] && [ -n "$(find "$dir" -type f -mmin "-$OLDER_MIN" -print -quit 2>/dev/null)" ]; then
|
|
112
112
|
continue # recently touched - spare it
|
|
113
113
|
fi
|
|
114
114
|
orphans+=("$dir")
|
|
@@ -32,7 +32,7 @@ const args = Object.fromEntries(
|
|
|
32
32
|
}),
|
|
33
33
|
);
|
|
34
34
|
|
|
35
|
-
const MODE = args.mode
|
|
35
|
+
const MODE = args.mode;
|
|
36
36
|
|
|
37
37
|
const PHASE_NAMES = [
|
|
38
38
|
"0:Init",
|
|
@@ -74,9 +74,9 @@ const MODES = {
|
|
|
74
74
|
},
|
|
75
75
|
};
|
|
76
76
|
|
|
77
|
-
const spec = MODES[MODE];
|
|
77
|
+
const spec = MODE ? MODES[MODE] : null;
|
|
78
78
|
if (!spec) {
|
|
79
|
-
console.error(`unknown mode: ${MODE}`);
|
|
79
|
+
console.error(MODE ? `unknown mode: ${MODE}` : "usage: gen-mode-dispatch.mjs --mode=<mode>");
|
|
80
80
|
console.error(`accepted: ${Object.keys(MODES).join(", ")}`);
|
|
81
81
|
process.exit(2);
|
|
82
82
|
}
|
|
@@ -44,8 +44,13 @@ echo "SSH key başarıyla oluşturuldu!"
|
|
|
44
44
|
# SSH agent'a ekle
|
|
45
45
|
eval "$(ssh-agent -s)" > /dev/null 2>&1
|
|
46
46
|
|
|
47
|
-
#
|
|
47
|
+
# SSH config ayarla (UseKeychain yalnızca macOS'ta geçerli bir seçenek;
|
|
48
|
+
# Linux'ta ssh bilinmeyen seçenek diye config'i reddeder)
|
|
48
49
|
SSH_CONFIG="$HOME/.ssh/config"
|
|
50
|
+
USE_KEYCHAIN_LINE=""
|
|
51
|
+
if [ "$(uname -s 2>/dev/null)" = "Darwin" ]; then
|
|
52
|
+
USE_KEYCHAIN_LINE=" UseKeychain yes"
|
|
53
|
+
fi
|
|
49
54
|
if ! grep -q "github.com" "$SSH_CONFIG" 2>/dev/null; then
|
|
50
55
|
cat >> "$SSH_CONFIG" <<EOF
|
|
51
56
|
|
|
@@ -54,7 +59,7 @@ Host github.com
|
|
|
54
59
|
User git
|
|
55
60
|
IdentityFile $KEY_PATH
|
|
56
61
|
AddKeysToAgent yes
|
|
57
|
-
|
|
62
|
+
${USE_KEYCHAIN_LINE}
|
|
58
63
|
EOF
|
|
59
64
|
chmod 600 "$SSH_CONFIG"
|
|
60
65
|
echo "SSH config güncellendi."
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
*
|
|
13
13
|
* Inputs:
|
|
14
14
|
* --root <path> Repo root. Default: cwd
|
|
15
|
-
* --stack <id> ios | android | node | python. Required.
|
|
15
|
+
* --stack <id> ios | android | node | python | go. Required.
|
|
16
16
|
* --out <path> Graph output. Default: ~/.claude/knowledge/<project>/code-graph.json
|
|
17
17
|
* --max-nodes N Refuse to write a graph larger than this. Default: 200000.
|
|
18
18
|
* Callers pass prefs.global.codeGraph.maxNodes. A tree that
|
|
@@ -88,7 +88,7 @@ function main() {
|
|
|
88
88
|
const { flags } = parseFlags(process.argv.slice(2));
|
|
89
89
|
const stack = flags.stack;
|
|
90
90
|
if (!stack || stack === true) {
|
|
91
|
-
process.stderr.write("graph-build: --stack <ios|android|node|python> required\n");
|
|
91
|
+
process.stderr.write("graph-build: --stack <ios|android|node|python|go> required\n");
|
|
92
92
|
process.exit(64);
|
|
93
93
|
}
|
|
94
94
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { readFileSync } from "node:fs";
|
|
3
|
+
import { pathToFileURL } from "node:url";
|
|
3
4
|
|
|
4
5
|
const SEQUENCES = [
|
|
5
6
|
":)",
|
|
@@ -77,7 +78,7 @@ async function readStdin() {
|
|
|
77
78
|
return Buffer.concat(chunks).toString("utf8");
|
|
78
79
|
}
|
|
79
80
|
|
|
80
|
-
const isMain = process.argv[1] && import.meta.url ===
|
|
81
|
+
const isMain = process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href;
|
|
81
82
|
if (isMain) {
|
|
82
83
|
const args = process.argv.slice(2);
|
|
83
84
|
const check = args.includes("--check");
|
|
@@ -51,7 +51,8 @@ Behaviour
|
|
|
51
51
|
- Windows / unknown platforms: backend unavailable; `doctor` prints remediation.
|
|
52
52
|
- Never logs the secret value. `set` accepts the value via argv (CLI) or via
|
|
53
53
|
stdin when the value is exactly `-` (preferred for scripts to avoid shell
|
|
54
|
-
history leak).
|
|
54
|
+
history leak). On macOS the write goes through `security -i` with the
|
|
55
|
+
command on stdin, so the value never appears on a child process argv.
|
|
55
56
|
- get returns the raw value to stdout with no trailing newline manipulation
|
|
56
57
|
beyond stripping the OS-level final \\n that `security -w` appends.
|
|
57
58
|
|
|
@@ -166,17 +167,17 @@ def set_(label: str, value: str, account: Optional[str] = None) -> None:
|
|
|
166
167
|
pf = _ensure_backend()
|
|
167
168
|
acct = _account_default(account)
|
|
168
169
|
if pf == "macos":
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
]
|
|
170
|
+
# `security -i` reads the add command from stdin, so the secret never
|
|
171
|
+
# lands on the security argv (visible to ps). Backslashes and double
|
|
172
|
+
# quotes are escaped for security's interactive tokenizer.
|
|
173
|
+
def quote(text: str) -> str:
|
|
174
|
+
return text.replace("\\", "\\\\").replace('"', '\\"')
|
|
175
|
+
|
|
176
|
+
command = (
|
|
177
|
+
f'add-generic-password -U -a "{quote(acct)}" -l "{quote(label)}" '
|
|
178
|
+
f'-s "{quote(label)}" -w "{quote(value)}"\n'
|
|
179
179
|
)
|
|
180
|
+
rc, _, err = _run(["/usr/bin/security", "-i"], input_value=command.encode("utf-8"))
|
|
180
181
|
if rc != 0:
|
|
181
182
|
sys.stderr.write(err.decode("utf-8", errors="replace"))
|
|
182
183
|
sys.exit(4)
|
|
@@ -141,7 +141,7 @@ const buckets = [...byBucket.keys()].sort().map((start) => {
|
|
|
141
141
|
: null,
|
|
142
142
|
reworkPerTask: round(list.reduce((s, t) => s + t.rework, 0) / n),
|
|
143
143
|
tokensPerTask: Math.round((totIn + totOut) / n),
|
|
144
|
-
cacheRatio: totIn ? round(totCached / totIn) : null,
|
|
144
|
+
cacheRatio: totIn + totCached ? round(totCached / (totIn + totCached)) : null,
|
|
145
145
|
memoryPrecision: totInjected ? round(totUsed / totInjected) : null,
|
|
146
146
|
};
|
|
147
147
|
});
|
|
@@ -248,7 +248,7 @@ function migrate(prefs) {
|
|
|
248
248
|
changes.push("initialized empty identities array");
|
|
249
249
|
}
|
|
250
250
|
|
|
251
|
-
// 4. keychainMapping -
|
|
251
|
+
// 4. keychainMapping - add every default service the file does not name yet
|
|
252
252
|
const km = out.global.keychainMapping || {};
|
|
253
253
|
const kmDefaults = defaultKeychainMapping();
|
|
254
254
|
let kmChanged = false;
|
|
@@ -23,7 +23,9 @@ TASK=""
|
|
|
23
23
|
while [ "$#" -gt 0 ]; do
|
|
24
24
|
case "$1" in
|
|
25
25
|
--strict) STRICT=true; shift ;;
|
|
26
|
-
--task)
|
|
26
|
+
--task)
|
|
27
|
+
[ "$#" -ge 2 ] || { echo "output-quality-check: --task needs a value" >&2; exit 1; }
|
|
28
|
+
TASK="$2"; shift 2 ;;
|
|
27
29
|
*) shift ;;
|
|
28
30
|
esac
|
|
29
31
|
done
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
import { existsSync, readFileSync } from "fs";
|
|
37
37
|
import { join } from "path";
|
|
38
38
|
import { homedir } from "os";
|
|
39
|
+
import { pathToFileURL } from "url";
|
|
39
40
|
|
|
40
41
|
const FIGMA_URL = /figma\.com\/(design|make|file)\//i;
|
|
41
42
|
|
|
@@ -233,6 +234,6 @@ function main(argv) {
|
|
|
233
234
|
return result.ok ? 0 : 1;
|
|
234
235
|
}
|
|
235
236
|
|
|
236
|
-
if (import.meta.url ===
|
|
237
|
+
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
237
238
|
process.exit(main(process.argv));
|
|
238
239
|
}
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
|
|
32
32
|
import { readFileSync, existsSync } from "node:fs";
|
|
33
33
|
import { join, isAbsolute } from "node:path";
|
|
34
|
+
import { pathToFileURL } from "node:url";
|
|
34
35
|
|
|
35
36
|
export function auditTodos(todos) {
|
|
36
37
|
const gaps = [];
|
|
@@ -89,7 +90,7 @@ function readJson(path) {
|
|
|
89
90
|
return JSON.parse(readFileSync(path, "utf8"));
|
|
90
91
|
}
|
|
91
92
|
|
|
92
|
-
const isMain = process.argv[1] && import.meta.url ===
|
|
93
|
+
const isMain = process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href;
|
|
93
94
|
if (isMain) {
|
|
94
95
|
const args = process.argv.slice(2);
|
|
95
96
|
const flag = (name) => {
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
# Pre-commit secret detection for multi-agent pipeline
|
|
3
3
|
# Scans staged git changes for accidentally committed secrets
|
|
4
|
-
# Exit 0 = clean, Exit
|
|
4
|
+
# Exit 0 = clean, Exit 2 = secrets found. The PreToolUse hook contract
|
|
5
|
+
# (install/templates/claude-hooks.json, agent-guard.sh) blocks the tool call
|
|
6
|
+
# only on exit 2, with the reason on stderr.
|
|
5
7
|
|
|
6
8
|
set -uo pipefail
|
|
7
9
|
|
|
@@ -56,6 +58,14 @@ process.stdin.on("end", () => {
|
|
|
56
58
|
fi
|
|
57
59
|
fi
|
|
58
60
|
|
|
61
|
+
# Staged paths from `git diff --cached --name-only` are repo-root-relative, so
|
|
62
|
+
# the `-f` tests below only see them from the repo root. Hooks fire with the
|
|
63
|
+
# caller's cwd, which is often a subdirectory.
|
|
64
|
+
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || true)"
|
|
65
|
+
if [ -n "$REPO_ROOT" ]; then
|
|
66
|
+
cd "$REPO_ROOT" || exit 0
|
|
67
|
+
fi
|
|
68
|
+
|
|
59
69
|
FOUND=0
|
|
60
70
|
|
|
61
71
|
# `file "$f" | grep -q "binary"` never matches real `file` output (it names a
|
|
@@ -74,14 +84,14 @@ scan_file() {
|
|
|
74
84
|
|
|
75
85
|
# .env files
|
|
76
86
|
if echo "$file" | grep -qE '\.env($|\.)'; then
|
|
77
|
-
echo "BLOCKED: .env file staged: $file"
|
|
87
|
+
echo "BLOCKED: .env file staged: $file" >&2
|
|
78
88
|
FOUND=1
|
|
79
89
|
return 0
|
|
80
90
|
fi
|
|
81
91
|
|
|
82
92
|
# Credentials files
|
|
83
93
|
if echo "$file" | grep -qiE '(credentials|secrets|tokens)\.(json|yaml|yml|plist)$'; then
|
|
84
|
-
echo "BLOCKED: Credentials file staged: $file"
|
|
94
|
+
echo "BLOCKED: Credentials file staged: $file" >&2
|
|
85
95
|
FOUND=1
|
|
86
96
|
return 0
|
|
87
97
|
fi
|
|
@@ -90,37 +100,37 @@ scan_file() {
|
|
|
90
100
|
|
|
91
101
|
# API keys / tokens (key = "long_string" pattern)
|
|
92
102
|
if echo "$content" | grep -qiE '(api[_-]?key|api[_-]?secret|access[_-]?token|auth[_-]?token|secret[_-]?key)\s*[:=]\s*["'"'"'][A-Za-z0-9+/=_-]{20,}'; then
|
|
93
|
-
echo "BLOCKED: Possible API key/token in $file"
|
|
103
|
+
echo "BLOCKED: Possible API key/token in $file" >&2
|
|
94
104
|
FOUND=1
|
|
95
105
|
fi
|
|
96
106
|
|
|
97
107
|
# AWS access keys
|
|
98
108
|
if echo "$content" | grep -qE 'AKIA[0-9A-Z]{16}'; then
|
|
99
|
-
echo "BLOCKED: AWS access key in $file"
|
|
109
|
+
echo "BLOCKED: AWS access key in $file" >&2
|
|
100
110
|
FOUND=1
|
|
101
111
|
fi
|
|
102
112
|
|
|
103
113
|
# Private keys
|
|
104
114
|
if echo "$content" | grep -qE 'BEGIN (RSA |EC |DSA |OPENSSH )?PRIVATE KEY'; then
|
|
105
|
-
echo "BLOCKED: Private key in $file"
|
|
115
|
+
echo "BLOCKED: Private key in $file" >&2
|
|
106
116
|
FOUND=1
|
|
107
117
|
fi
|
|
108
118
|
|
|
109
119
|
# Firebase/GCP service account JSON
|
|
110
120
|
if echo "$content" | grep -qE '"type"\s*:\s*"service_account"'; then
|
|
111
|
-
echo "BLOCKED: Service account JSON in $file"
|
|
121
|
+
echo "BLOCKED: Service account JSON in $file" >&2
|
|
112
122
|
FOUND=1
|
|
113
123
|
fi
|
|
114
124
|
|
|
115
125
|
# High-signal provider token prefixes (low false-positive rate)
|
|
116
126
|
if echo "$content" | grep -qE '(ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9]{36}|github_pat_[A-Za-z0-9_]{60,}|xox[baprs]-[A-Za-z0-9-]{12,}|sk_live_[A-Za-z0-9]{20,}|rk_live_[A-Za-z0-9]{20,}|AIza[0-9A-Za-z_-]{35}|npm_[A-Za-z0-9]{36}|glpat-[A-Za-z0-9_-]{20,}'; then
|
|
117
|
-
echo "BLOCKED: Provider access token in $file"
|
|
127
|
+
echo "BLOCKED: Provider access token in $file" >&2
|
|
118
128
|
FOUND=1
|
|
119
129
|
fi
|
|
120
130
|
|
|
121
131
|
# JWT (three base64url segments - header.payload.signature)
|
|
122
132
|
if echo "$content" | grep -qE 'eyJ[A-Za-z0-9_-]{10,}\.eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}'; then
|
|
123
|
-
echo "BLOCKED: JWT in $file"
|
|
133
|
+
echo "BLOCKED: JWT in $file" >&2
|
|
124
134
|
FOUND=1
|
|
125
135
|
fi
|
|
126
136
|
|
|
@@ -191,7 +201,7 @@ scan_file() {
|
|
|
191
201
|
if (H >= 4.2) { print s; exit }
|
|
192
202
|
}')
|
|
193
203
|
if [ -n "$entropy_hit" ]; then
|
|
194
|
-
echo "BLOCKED: High-entropy string (possible secret) in $file"
|
|
204
|
+
echo "BLOCKED: High-entropy string (possible secret) in $file" >&2
|
|
195
205
|
FOUND=1
|
|
196
206
|
fi
|
|
197
207
|
fi
|
|
@@ -234,9 +244,9 @@ if [ "$SCAN_UNSTAGED" = "1" ]; then
|
|
|
234
244
|
fi
|
|
235
245
|
|
|
236
246
|
if [ $FOUND -eq 1 ]; then
|
|
237
|
-
echo ""
|
|
238
|
-
echo "Secret check failed. Remove secrets from staged files before committing."
|
|
239
|
-
exit
|
|
247
|
+
echo "" >&2
|
|
248
|
+
echo "Secret check failed. Remove secrets from staged files before committing." >&2
|
|
249
|
+
exit 2
|
|
240
250
|
fi
|
|
241
251
|
|
|
242
252
|
exit 0
|
|
@@ -151,7 +151,7 @@ while IFS= read -r -d '' d; do
|
|
|
151
151
|
# so a concurrent run keeps a resumable log dir. --task is an explicit,
|
|
152
152
|
# deliberate target and bypasses the grace.
|
|
153
153
|
if [ "$GRACE_MIN" -gt 0 ] && [ -z "$TASK" ] &&
|
|
154
|
-
find "$d" -mmin "-$GRACE_MIN" -print 2>/dev/null
|
|
154
|
+
[ -n "$(find "$d" -mmin "-$GRACE_MIN" -print -quit 2>/dev/null)" ]; then
|
|
155
155
|
skipped_active=$((skipped_active + 1))
|
|
156
156
|
continue
|
|
157
157
|
fi
|
|
@@ -25,7 +25,9 @@ shift || true
|
|
|
25
25
|
SPANS_FILE=""
|
|
26
26
|
while [ $# -gt 0 ]; do
|
|
27
27
|
case "$1" in
|
|
28
|
-
--otel-spans)
|
|
28
|
+
--otel-spans)
|
|
29
|
+
[ $# -ge 2 ] || { echo "render-agent-log-cost: --otel-spans needs a path" >&2; exit 1; }
|
|
30
|
+
SPANS_FILE="$2"; shift 2 ;;
|
|
29
31
|
*) shift ;;
|
|
30
32
|
esac
|
|
31
33
|
done
|
|
@@ -19,7 +19,9 @@ shift || true
|
|
|
19
19
|
SPANS_FILE=""
|
|
20
20
|
while [ $# -gt 0 ]; do
|
|
21
21
|
case "$1" in
|
|
22
|
-
--otel-spans)
|
|
22
|
+
--otel-spans)
|
|
23
|
+
[ $# -ge 2 ] || { echo "render-cost-summary: --otel-spans needs a path" >&2; exit 1; }
|
|
24
|
+
SPANS_FILE="$2"; shift 2 ;;
|
|
23
25
|
*) shift ;;
|
|
24
26
|
esac
|
|
25
27
|
done
|
|
@@ -71,7 +73,7 @@ if [ -n "$tracker_file" ]; then
|
|
|
71
73
|
(.phases // {} | to_entries)
|
|
72
74
|
end)
|
|
73
75
|
| [ .[] |
|
|
74
|
-
select(.value.tokens_in // 0 > 0 or .value.tokens_out // 0 > 0) |
|
|
76
|
+
select(((.value.tokens_in // 0) > 0) or ((.value.tokens_out // 0) > 0)) |
|
|
75
77
|
{
|
|
76
78
|
phase: .key,
|
|
77
79
|
phase_name: (.value.name // .key),
|
|
@@ -44,11 +44,13 @@ TASK_ID="${1:?usage: render-work-summary.sh <task-id>}"
|
|
|
44
44
|
shift || true
|
|
45
45
|
|
|
46
46
|
WORKTREE=""; BRANCH=""; BASE=""
|
|
47
|
+
need_value() { [ $# -ge 2 ] || { echo "render-work-summary: $1 needs a value" >&2; exit 1; }; }
|
|
48
|
+
|
|
47
49
|
while [ $# -gt 0 ]; do
|
|
48
50
|
case "$1" in
|
|
49
|
-
--worktree) WORKTREE="$2"; shift 2 ;;
|
|
50
|
-
--branch) BRANCH="$2"; shift 2 ;;
|
|
51
|
-
--base-branch) BASE="$2"; shift 2 ;;
|
|
51
|
+
--worktree) need_value "$@"; WORKTREE="$2"; shift 2 ;;
|
|
52
|
+
--branch) need_value "$@"; BRANCH="$2"; shift 2 ;;
|
|
53
|
+
--base-branch) need_value "$@"; BASE="$2"; shift 2 ;;
|
|
52
54
|
*) shift ;;
|
|
53
55
|
esac
|
|
54
56
|
done
|
|
@@ -30,6 +30,7 @@ import { promises as fs } from "node:fs";
|
|
|
30
30
|
import { existsSync, statSync } from "node:fs";
|
|
31
31
|
import path from "node:path";
|
|
32
32
|
import process from "node:process";
|
|
33
|
+
import { matchesGlob } from "./_path-match.mjs";
|
|
33
34
|
|
|
34
35
|
// ---- CLI args --------------------------------------------------------------
|
|
35
36
|
|
|
@@ -142,8 +143,8 @@ async function walk(root, args) {
|
|
|
142
143
|
continue;
|
|
143
144
|
}
|
|
144
145
|
const rel = path.relative(root, full);
|
|
145
|
-
if (args.include && !args.include.some((g) => rel
|
|
146
|
-
if (args.exclude && args.exclude.some((g) => rel
|
|
146
|
+
if (args.include && !args.include.some((g) => matchesGlob(rel, g))) continue;
|
|
147
|
+
if (args.exclude && args.exclude.some((g) => matchesGlob(rel, g))) continue;
|
|
147
148
|
out.push({ path: rel, lang: LANG_EXT[ext], abs: full });
|
|
148
149
|
}
|
|
149
150
|
}
|
|
@@ -34,10 +34,14 @@ THRESHOLD="medium"
|
|
|
34
34
|
|
|
35
35
|
while [ $# -gt 0 ]; do
|
|
36
36
|
case "$1" in
|
|
37
|
-
--root)
|
|
37
|
+
--root)
|
|
38
|
+
[ $# -ge 2 ] || { echo "scan-skills: --root needs a value" >&2; exit 64; }
|
|
39
|
+
ROOT="$2"; shift 2 ;;
|
|
38
40
|
--strict) STRICT=1; shift ;;
|
|
39
41
|
--json) JSON=1; shift ;;
|
|
40
|
-
--threshold)
|
|
42
|
+
--threshold)
|
|
43
|
+
[ $# -ge 2 ] || { echo "scan-skills: --threshold needs a value" >&2; exit 64; }
|
|
44
|
+
THRESHOLD="$2"; shift 2 ;;
|
|
41
45
|
--help|-h)
|
|
42
46
|
sed -n '1,30p' "$0" | sed 's/^# \{0,1\}//'
|
|
43
47
|
exit 0
|
|
@@ -42,16 +42,18 @@ LIMIT=20
|
|
|
42
42
|
QUERY=""
|
|
43
43
|
SEMANTIC=0
|
|
44
44
|
|
|
45
|
+
need_value() { [ $# -ge 2 ] || { echo "search-logs: $1 needs a value" >&2; exit 64; }; }
|
|
46
|
+
|
|
45
47
|
while [ $# -gt 0 ]; do
|
|
46
48
|
case "$1" in
|
|
47
|
-
--root) ROOT="$2"; shift 2 ;;
|
|
48
|
-
--project) PROJECT="$2"; shift 2 ;;
|
|
49
|
-
--since) SINCE="$2"; shift 2 ;;
|
|
50
|
-
--phase) PHASE="$2"; shift 2 ;;
|
|
49
|
+
--root) need_value "$@"; ROOT="$2"; shift 2 ;;
|
|
50
|
+
--project) need_value "$@"; PROJECT="$2"; shift 2 ;;
|
|
51
|
+
--since) need_value "$@"; SINCE="$2"; shift 2 ;;
|
|
52
|
+
--phase) need_value "$@"; PHASE="$2"; shift 2 ;;
|
|
51
53
|
--json) JSON=1; shift ;;
|
|
52
54
|
--tsv) TSV=1; shift ;;
|
|
53
55
|
--semantic) SEMANTIC=1; shift ;;
|
|
54
|
-
--limit) LIMIT="$2"; shift 2 ;;
|
|
56
|
+
--limit) need_value "$@"; LIMIT="$2"; shift 2 ;;
|
|
55
57
|
--help|-h)
|
|
56
58
|
awk 'NR==1{next} /^[^#]/{exit} {sub(/^# ?/,""); print}' "$0"
|
|
57
59
|
exit 0
|
|
@@ -78,7 +80,7 @@ fi
|
|
|
78
80
|
# --limit (passed as --top N). --since/--phase have no meaning here.
|
|
79
81
|
if [ "$SEMANTIC" -eq 1 ]; then
|
|
80
82
|
TM_SCRIPT="$SCRIPT_DIR/triage-memory.mjs"
|
|
81
|
-
if [ ! -
|
|
83
|
+
if [ ! -f "$TM_SCRIPT" ] || ! command -v node >/dev/null 2>&1; then
|
|
82
84
|
echo "search-logs: --semantic requires node + triage-memory.mjs" >&2
|
|
83
85
|
exit 1
|
|
84
86
|
fi
|
|
@@ -18,7 +18,9 @@ set -euo pipefail
|
|
|
18
18
|
ROOT_OVERRIDE=""
|
|
19
19
|
while [ $# -gt 0 ]; do
|
|
20
20
|
case "$1" in
|
|
21
|
-
--root)
|
|
21
|
+
--root)
|
|
22
|
+
[ $# -ge 2 ] || { echo "sign-skills: --root needs a value" >&2; exit 1; }
|
|
23
|
+
ROOT_OVERRIDE="$2"; shift 2 ;;
|
|
22
24
|
*) shift ;;
|
|
23
25
|
esac
|
|
24
26
|
done
|
|
@@ -95,7 +95,7 @@ echo ""
|
|
|
95
95
|
echo "→ 3. No personal-data hardcodes in generic docs"
|
|
96
96
|
# These are patterns that must be placeholders, never literals
|
|
97
97
|
PERSONAL_HARDCODES=(
|
|
98
|
-
"${USER}_tkgithub"
|
|
98
|
+
"${USER:-$(id -un)}_tkgithub"
|
|
99
99
|
)
|
|
100
100
|
for p in "${PERSONAL_HARDCODES[@]}"; do
|
|
101
101
|
FOUND=$(find "$CLAUDE_CMDS" -name SKILL.md -exec grep -l -F -- "$p" {} + 2>/dev/null || true)
|