@mmerterden/multi-agent-pipeline 16.18.0 → 16.20.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 +68 -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/_codex-agents.mjs +2 -2
- package/install/_common.mjs +25 -1
- package/install/_dev-only-files.mjs +3 -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 +4 -3
- package/pipeline/agents/android-architect.md +1 -0
- package/pipeline/agents/backend-architect.md +1 -0
- package/pipeline/agents/code-reviewer.md +1 -0
- package/pipeline/agents/dev-critic.md +2 -1
- package/pipeline/agents/explorer.md +1 -0
- package/pipeline/agents/ios-architect.md +1 -0
- package/pipeline/agents/security-auditor.md +1 -0
- package/pipeline/agents/task-clarifier.md +1 -0
- 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/manual-test/SKILL.md +5 -1
- package/pipeline/commands/multi-agent/resume/SKILL.md +1 -0
- 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 +24 -2
- package/pipeline/commands/multi-agent/sync/SKILL.md +2 -2
- package/pipeline/commands/sim-test.md +64 -20
- 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/channels/pr.md +22 -4
- package/pipeline/multi-agent-refs/cross-cli-contract.md +1 -1
- package/pipeline/multi-agent-refs/features/autopilot-circuit-breaker.md +15 -2
- package/pipeline/multi-agent-refs/features/review-delta.md +89 -0
- package/pipeline/multi-agent-refs/features/scope-check.md +41 -0
- package/pipeline/multi-agent-refs/features/verify-by-test.md +6 -5
- package/pipeline/multi-agent-refs/features/worktree-finalize.md +1 -1
- package/pipeline/multi-agent-refs/outside-the-pipeline.md +6 -6
- package/pipeline/multi-agent-refs/payload-contracts.md +1 -1
- 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-3-dev.md +17 -2
- package/pipeline/multi-agent-refs/phases/phase-4-review.md +67 -24
- package/pipeline/multi-agent-refs/phases/phase-5-test.md +10 -0
- package/pipeline/multi-agent-refs/phases/phase-6-commit.md +2 -0
- package/pipeline/multi-agent-refs/phases/phase-7-report.md +4 -2
- package/pipeline/multi-agent-refs/rules.md +2 -2
- 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 +130 -1
- package/pipeline/schemas/dev-critic-output.schema.json +5 -0
- package/pipeline/schemas/prefs.schema.json +47 -0
- package/pipeline/schemas/reviewer-output.schema.json +7 -2
- package/pipeline/schemas/scope-check.schema.json +55 -0
- package/pipeline/schemas/token-budget.json +3 -3
- package/pipeline/schemas/triage-output.schema.json +12 -2
- package/pipeline/scripts/README.md +3 -2
- package/pipeline/scripts/_fingerprint.mjs +173 -0
- 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/evidence-gate.mjs +73 -5
- package/pipeline/scripts/finding-fingerprint.mjs +101 -0
- 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/review-delta.mjs +217 -0
- package/pipeline/scripts/run-metrics.mjs +20 -0
- package/pipeline/scripts/scan-skills.sh +6 -2
- package/pipeline/scripts/scope-check-gate.mjs +90 -0
- package/pipeline/scripts/search-logs.sh +8 -6
- package/pipeline/scripts/sign-skills.sh +3 -1
- package/pipeline/scripts/smoke-cross-cli-behavior.sh +12 -5
- 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/validate-reviewer.mjs +6 -0
- package/pipeline/scripts/validate-triage.mjs +20 -0
- 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-store-ready/SKILL.md +5 -0
- 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
|
@@ -12,11 +12,11 @@
|
|
|
12
12
|
// Pattern source: karpathy/llm-council backend/council.py stage 2, which labels
|
|
13
13
|
// peer answers "Response A/B/C" and keeps label_to_model out of the prompt.
|
|
14
14
|
//
|
|
15
|
-
// A residual worth naming:
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
// the guess - llm-council's four-model council has
|
|
19
|
-
//
|
|
15
|
+
// A residual worth naming: on both hosts the triage model is one of the three
|
|
16
|
+
// reviewers, so with the label set {Source A, Source B, Source C} it retains a
|
|
17
|
+
// one-in-three prior on which findings are its own. Anonymization removes the
|
|
18
|
+
// signal, not the guess - llm-council's four-model council has the same property
|
|
19
|
+
// at one in four. The value here is that nothing TELLS the judge.
|
|
20
20
|
//
|
|
21
21
|
// What this does NOT do: scrub identity out of free text. A reviewer that writes
|
|
22
22
|
// "as Sonnet would" in `issue`, or whose prose style is recognisable, is not
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
// Exit codes: 0 ok, 64 usage, 65 input is not JSON.
|
|
37
37
|
|
|
38
38
|
import { readFileSync, writeFileSync } from "node:fs";
|
|
39
|
+
import { pathToFileURL } from "node:url";
|
|
39
40
|
|
|
40
41
|
const IDENTITY_KEYS = [
|
|
41
42
|
"reviewer",
|
|
@@ -136,7 +137,7 @@ export function anonymize(input, { seed } = {}) {
|
|
|
136
137
|
return { findings: tagged, map: { seed: seedText, labelToModel, malformed } };
|
|
137
138
|
}
|
|
138
139
|
|
|
139
|
-
const isMain = process.argv[1] && import.meta.url ===
|
|
140
|
+
const isMain = process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href;
|
|
140
141
|
if (isMain) {
|
|
141
142
|
const args = process.argv.slice(2);
|
|
142
143
|
const flag = (name) => {
|
|
@@ -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
|
|
|
@@ -11,13 +11,21 @@
|
|
|
11
11
|
// node pipeline/scripts/evidence-gate.mjs --claim build --status passed --evidence build.log
|
|
12
12
|
// node pipeline/scripts/evidence-gate.mjs --claim test --status passed --evidence test.log \
|
|
13
13
|
// --success-pattern 'All tests passed' --failure-pattern 'FAILED'
|
|
14
|
+
// node pipeline/scripts/evidence-gate.mjs --claim manual --status passed --evidence manual-test.json
|
|
14
15
|
//
|
|
15
16
|
// Flags:
|
|
16
|
-
// --claim build | test | review
|
|
17
|
+
// --claim build | test | review | manual
|
|
18
|
+
// build/test/review select default success/failure markers;
|
|
19
|
+
// manual is JSON-based (Phase 5 manual-test.json, see below)
|
|
17
20
|
// --status the claimed status (only "passed" is gated; others pass through)
|
|
18
21
|
// --evidence <path> the log / artifact that must substantiate a "passed" claim
|
|
19
|
-
// --success-pattern override the default success regex for the claim type
|
|
20
|
-
// --failure-pattern override the default failure regex for the claim type
|
|
22
|
+
// --success-pattern override the default success regex for the claim type (marker claims only)
|
|
23
|
+
// --failure-pattern override the default failure regex for the claim type (marker claims only)
|
|
24
|
+
//
|
|
25
|
+
// The manual claim reads a JSON document instead of scanning for markers:
|
|
26
|
+
// { "criteria": [ { "spec", "observed", "verdict": "pass|fail|not-tested", "reason"?, ... } ], ... }
|
|
27
|
+
// criteria must be a non-empty array; every item needs spec, observed and a
|
|
28
|
+
// valid verdict; any "fail" is decisive; "not-tested" needs a non-empty reason.
|
|
21
29
|
//
|
|
22
30
|
// Exit codes:
|
|
23
31
|
// 0 - status is not "passed" (nothing to prove), OR evidence substantiates the pass
|
|
@@ -47,6 +55,10 @@ const DEFAULT_MARKERS = {
|
|
|
47
55
|
},
|
|
48
56
|
};
|
|
49
57
|
|
|
58
|
+
const JSON_CLAIMS = new Set(["manual"]);
|
|
59
|
+
const CLAIMS = [...Object.keys(DEFAULT_MARKERS), ...JSON_CLAIMS];
|
|
60
|
+
const MANUAL_VERDICTS = new Set(["pass", "fail", "not-tested"]);
|
|
61
|
+
|
|
50
62
|
const MAX_PATTERN_LEN = 200;
|
|
51
63
|
|
|
52
64
|
// Compile a caller-supplied pattern safely: cap length and catch a bad regex so
|
|
@@ -101,12 +113,64 @@ function usage(msg) {
|
|
|
101
113
|
process.exit(2);
|
|
102
114
|
}
|
|
103
115
|
|
|
116
|
+
function nonEmptyString(v) {
|
|
117
|
+
return typeof v === "string" && v.trim().length > 0;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Manual-test evidence is a structured document, not a log: every acceptance
|
|
121
|
+
// criterion must say what was observed and how it came out. A "fail" anywhere
|
|
122
|
+
// is decisive; an untested criterion is only acceptable when it says why.
|
|
123
|
+
function gateManual(claim, evidence, body) {
|
|
124
|
+
let doc;
|
|
125
|
+
try {
|
|
126
|
+
doc = JSON.parse(body);
|
|
127
|
+
} catch (err) {
|
|
128
|
+
fail(`${claim} evidence is not valid JSON: ${evidence} (${err.message}) (default-FAIL)`);
|
|
129
|
+
}
|
|
130
|
+
const criteria = doc && typeof doc === "object" ? doc.criteria : undefined;
|
|
131
|
+
if (!Array.isArray(criteria) || criteria.length === 0) {
|
|
132
|
+
fail(`${claim} claims passed but evidence has no criteria: ${evidence} (default-FAIL)`);
|
|
133
|
+
}
|
|
134
|
+
criteria.forEach((item, i) => {
|
|
135
|
+
const label = `criteria[${i}]`;
|
|
136
|
+
if (!item || typeof item !== "object") {
|
|
137
|
+
fail(`${claim} evidence ${label} is not an object: ${evidence} (default-FAIL)`);
|
|
138
|
+
}
|
|
139
|
+
if (!nonEmptyString(item.spec)) {
|
|
140
|
+
fail(`${claim} evidence ${label} has no spec: ${evidence} (default-FAIL)`);
|
|
141
|
+
}
|
|
142
|
+
if (!nonEmptyString(item.observed)) {
|
|
143
|
+
fail(`${claim} evidence ${label} has no observed value: ${evidence} (default-FAIL)`);
|
|
144
|
+
}
|
|
145
|
+
if (!MANUAL_VERDICTS.has(item.verdict)) {
|
|
146
|
+
fail(
|
|
147
|
+
`${claim} evidence ${label} verdict must be one of pass|fail|not-tested: ${evidence} (default-FAIL)`,
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
const failed = criteria.find((item) => item.verdict === "fail");
|
|
152
|
+
if (failed) {
|
|
153
|
+
fail(
|
|
154
|
+
`${claim} evidence shows a failed criterion "${failed.spec}" - pass claim contradicted by ${evidence}`,
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
const untested = criteria.find(
|
|
158
|
+
(item) => item.verdict === "not-tested" && !nonEmptyString(item.reason),
|
|
159
|
+
);
|
|
160
|
+
if (untested) {
|
|
161
|
+
fail(
|
|
162
|
+
`${claim} evidence has not-tested criterion "${untested.spec}" without a reason - pass claim unverified by ${evidence} (default-FAIL)`,
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
ok(`${claim} pass claim substantiated by ${criteria.length} criteria in ${evidence}`);
|
|
166
|
+
}
|
|
167
|
+
|
|
104
168
|
const args = parseArgs(process.argv.slice(2));
|
|
105
169
|
const claim = args.claim;
|
|
106
170
|
const status = args.status;
|
|
107
171
|
|
|
108
|
-
if (!claim || !
|
|
109
|
-
usage(`--claim must be one of: ${
|
|
172
|
+
if (!claim || !CLAIMS.includes(claim)) {
|
|
173
|
+
usage(`--claim must be one of: ${CLAIMS.join(", ")}`);
|
|
110
174
|
}
|
|
111
175
|
if (typeof status !== "string") {
|
|
112
176
|
usage("--status is required");
|
|
@@ -138,6 +202,10 @@ if (body.trim().length === 0) {
|
|
|
138
202
|
fail(`${claim} claims passed but evidence file is blank: ${evidence} (default-FAIL)`);
|
|
139
203
|
}
|
|
140
204
|
|
|
205
|
+
if (JSON_CLAIMS.has(claim)) {
|
|
206
|
+
gateManual(claim, evidence, body);
|
|
207
|
+
}
|
|
208
|
+
|
|
141
209
|
const successRe = userRegExp(args["success-pattern"], DEFAULT_MARKERS[claim].success, "success");
|
|
142
210
|
const failureRe = userRegExp(args["failure-pattern"], DEFAULT_MARKERS[claim].failure, "failure");
|
|
143
211
|
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* finding-fingerprint.mjs - stamp every review finding with its stable id.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* node finding-fingerprint.mjs annotate <path|-> [--kind reviewer|triage|dev-critic|auto] [--in-place]
|
|
7
|
+
* node finding-fingerprint.mjs compute --file <path> --issue <text> [--rule-id <id>]
|
|
8
|
+
*
|
|
9
|
+
* `annotate` prints the annotated JSON (or rewrites the file with --in-place)
|
|
10
|
+
* and reports counts on stderr. `compute` prints {"fingerprint":"F:..."}.
|
|
11
|
+
*
|
|
12
|
+
* Exit codes: 0 ok, 1 unparseable input or unknown shape, 64 usage.
|
|
13
|
+
* Zero dependencies. Library half lives in _fingerprint.mjs.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
17
|
+
|
|
18
|
+
import { annotate, findingFingerprint, KINDS } from "./_fingerprint.mjs";
|
|
19
|
+
|
|
20
|
+
const USAGE = `usage:
|
|
21
|
+
finding-fingerprint.mjs annotate <path|-> [--kind ${KINDS.join("|")}|auto] [--in-place]
|
|
22
|
+
finding-fingerprint.mjs compute --file <path> --issue <text> [--rule-id <id>]`;
|
|
23
|
+
|
|
24
|
+
function parseArgs(argv) {
|
|
25
|
+
const opts = { _: [] };
|
|
26
|
+
for (let i = 0; i < argv.length; i++) {
|
|
27
|
+
const a = argv[i];
|
|
28
|
+
if (a === "--in-place") opts.inPlace = true;
|
|
29
|
+
else if (a === "--kind") opts.kind = argv[++i];
|
|
30
|
+
else if (a === "--file") opts.file = argv[++i];
|
|
31
|
+
else if (a === "--issue") opts.issue = argv[++i];
|
|
32
|
+
else if (a === "--rule-id") opts.ruleId = argv[++i];
|
|
33
|
+
else if (a.startsWith("--")) return null;
|
|
34
|
+
else opts._.push(a);
|
|
35
|
+
}
|
|
36
|
+
return opts;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function readSource(path) {
|
|
40
|
+
return path === "-" ? readFileSync(0, "utf-8") : readFileSync(path, "utf-8");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function main() {
|
|
44
|
+
const [command, ...rest] = process.argv.slice(2);
|
|
45
|
+
const opts = parseArgs(rest);
|
|
46
|
+
if (!opts) {
|
|
47
|
+
console.error(USAGE);
|
|
48
|
+
return 64;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (command === "compute") {
|
|
52
|
+
if (!opts.file || !opts.issue) {
|
|
53
|
+
console.error(USAGE);
|
|
54
|
+
return 64;
|
|
55
|
+
}
|
|
56
|
+
const fingerprint = findingFingerprint({
|
|
57
|
+
file: opts.file,
|
|
58
|
+
issue: opts.issue,
|
|
59
|
+
ruleId: opts.ruleId,
|
|
60
|
+
});
|
|
61
|
+
process.stdout.write(JSON.stringify({ fingerprint }) + "\n");
|
|
62
|
+
return 0;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (command !== "annotate" || opts._.length !== 1) {
|
|
66
|
+
console.error(USAGE);
|
|
67
|
+
return 64;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const path = opts._[0];
|
|
71
|
+
if (opts.inPlace && path === "-") {
|
|
72
|
+
console.error("error: --in-place needs a file path, not STDIN");
|
|
73
|
+
return 64;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
let doc;
|
|
77
|
+
try {
|
|
78
|
+
doc = JSON.parse(readSource(path));
|
|
79
|
+
} catch (err) {
|
|
80
|
+
console.error(`error: cannot read ${path}: ${err.message}`);
|
|
81
|
+
return 1;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
let result;
|
|
85
|
+
try {
|
|
86
|
+
result = annotate(doc, opts.kind ?? "auto");
|
|
87
|
+
} catch (err) {
|
|
88
|
+
console.error(`error: ${err.message}`);
|
|
89
|
+
return 1;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const text = JSON.stringify(result.doc, null, 2) + "\n";
|
|
93
|
+
if (opts.inPlace) writeFileSync(path, text);
|
|
94
|
+
else process.stdout.write(text);
|
|
95
|
+
console.error(
|
|
96
|
+
`finding-fingerprint: ${result.kind}, ${result.computed} computed, ${result.kept} kept`,
|
|
97
|
+
);
|
|
98
|
+
return 0;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
process.exit(main());
|
|
@@ -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) => {
|