sanook-cli 0.4.0 → 0.5.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/.env.example +19 -0
- package/CHANGELOG.md +144 -0
- package/README.md +153 -20
- package/README.th.md +136 -0
- package/dist/agentContext.js +4 -0
- package/dist/approval.js +6 -0
- package/dist/bin.js +394 -51
- package/dist/brain.js +92 -59
- package/dist/brand.js +47 -0
- package/dist/checkpoint.js +37 -0
- package/dist/commands.js +86 -6
- package/dist/compaction.js +76 -5
- package/dist/config.js +100 -12
- package/dist/cost.js +60 -3
- package/dist/doctor.js +92 -0
- package/dist/gateway/auth.js +2 -2
- package/dist/gateway/ledger.js +2 -2
- package/dist/gateway/scheduler.js +1 -0
- package/dist/gateway/serve.js +6 -4
- package/dist/gateway/server.js +10 -2
- package/dist/git.js +11 -2
- package/dist/hooks.js +43 -17
- package/dist/knowledge.js +48 -49
- package/dist/loop.js +182 -66
- package/dist/lsp/client.js +173 -0
- package/dist/lsp/framing.js +56 -0
- package/dist/lsp/index.js +138 -0
- package/dist/lsp/servers.js +82 -0
- package/dist/mcp-server.js +244 -0
- package/dist/mcp.js +184 -29
- package/dist/memory-store.js +559 -0
- package/dist/memory.js +143 -29
- package/dist/orchestrate.js +150 -0
- package/dist/providers/codex.js +2 -2
- package/dist/providers/keys.js +3 -2
- package/dist/providers/registry.js +133 -1
- package/dist/repomap.js +93 -0
- package/dist/search/chunk.js +158 -0
- package/dist/search/embed-store.js +187 -0
- package/dist/search/engine.js +203 -0
- package/dist/search/fuse.js +35 -0
- package/dist/search/index-core.js +187 -0
- package/dist/search/indexer.js +241 -0
- package/dist/search/store.js +77 -0
- package/dist/session.js +42 -8
- package/dist/skill-install.js +10 -10
- package/dist/skills.js +12 -9
- package/dist/summarize.js +31 -0
- package/dist/tools/bash.js +21 -2
- package/dist/tools/diagnostics.js +41 -0
- package/dist/tools/edit.js +29 -7
- package/dist/tools/index.js +8 -1
- package/dist/tools/list.js +7 -2
- package/dist/tools/permission.js +90 -9
- package/dist/tools/read.js +23 -4
- package/dist/tools/remember.js +1 -1
- package/dist/tools/sandbox.js +61 -0
- package/dist/tools/search.js +105 -4
- package/dist/tools/task.js +195 -29
- package/dist/tools/timeout.js +35 -0
- package/dist/tools/util.js +10 -0
- package/dist/tools/write.js +6 -4
- package/dist/trust.js +89 -0
- package/dist/ui/app.js +218 -27
- package/dist/ui/banner.js +4 -9
- package/dist/ui/history.js +30 -0
- package/dist/ui/mentions.js +44 -0
- package/dist/ui/setup.js +6 -5
- package/dist/ui/useEditor.js +83 -0
- package/dist/update.js +114 -0
- package/dist/worktree.js +173 -0
- package/package.json +11 -5
- package/scripts/postinstall.mjs +33 -0
- package/second-brain/.agents/_Index.md +30 -0
- package/second-brain/.agents/skills/_Index.md +30 -0
- package/second-brain/.agents/workflows/_Index.md +30 -0
- package/second-brain/AGENTS.md +4 -4
- package/second-brain/Acceptance/_Index.md +30 -0
- package/second-brain/Acceptance/golden-case-template.md +39 -0
- package/second-brain/Areas/_Index.md +30 -0
- package/second-brain/Bugs/System-OS/_Index.md +30 -0
- package/second-brain/Bugs/_Index.md +30 -0
- package/second-brain/CLAUDE.md +4 -1
- package/second-brain/Checklists/_Index.md +30 -0
- package/second-brain/Checklists/preflight-postflight-template.md +29 -0
- package/second-brain/Distillations/_Index.md +30 -0
- package/second-brain/Entities/_Index.md +30 -0
- package/second-brain/Entities/entity-template.md +33 -0
- package/second-brain/Evals/_Index.md +30 -0
- package/second-brain/Evals/correction-pairs.md +24 -0
- package/second-brain/Evals/failure-taxonomy.md +24 -0
- package/second-brain/Evals/golden-set.md +25 -0
- package/second-brain/Evals/quality-ledger.md +23 -0
- package/second-brain/Evals/self-eval-rubric.md +23 -0
- package/second-brain/GEMINI.md +4 -4
- package/second-brain/Goals/_Index.md +30 -0
- package/second-brain/Handoffs/_Index.md +30 -0
- package/second-brain/Home.md +7 -0
- package/second-brain/Intake/Raw Sources/_Index.md +30 -0
- package/second-brain/Intake/_Index.md +30 -0
- package/second-brain/Intake/_Quarantine/_Index.md +30 -0
- package/second-brain/Learning/_Index.md +30 -0
- package/second-brain/Playbooks/_Index.md +30 -0
- package/second-brain/Playbooks/playbook-template.md +23 -0
- package/second-brain/Projects/_Index.md +30 -0
- package/second-brain/Prompts/_Index.md +30 -0
- package/second-brain/README.md +2 -1
- package/second-brain/Research/_Index.md +30 -0
- package/second-brain/Retrospectives/_Index.md +30 -0
- package/second-brain/Reviews/_Index.md +30 -0
- package/second-brain/Runbooks/_Index.md +30 -0
- package/second-brain/Runbooks/eval-loop.md +24 -0
- package/second-brain/Sessions/_Index.md +30 -0
- package/second-brain/Shared/AI-Context-Index.md +20 -0
- package/second-brain/Shared/AI-Threads/_Index.md +30 -0
- package/second-brain/Shared/Archive/_Index.md +30 -0
- package/second-brain/Shared/Assets/_Index.md +30 -0
- package/second-brain/Shared/Context-Packs/_Index.md +30 -0
- package/second-brain/Shared/Context7-Docs/_Index.md +30 -0
- package/second-brain/Shared/Coordination/NOW.md +28 -0
- package/second-brain/Shared/Coordination/_Index.md +30 -0
- package/second-brain/Shared/Coordination/agent-registry.md +24 -0
- package/second-brain/Shared/Coordination/task-board/_Index.md +30 -0
- package/second-brain/Shared/Coordination/task-board/task-template.md +43 -0
- package/second-brain/Shared/Coordination/task-board.md +32 -0
- package/second-brain/Shared/Core-Facts/_Index.md +30 -0
- package/second-brain/Shared/Decision-Memory/_Index.md +30 -0
- package/second-brain/Shared/Glossary/_Index.md +30 -0
- package/second-brain/Shared/Memory-Inbox/_Index.md +30 -0
- package/second-brain/Shared/Operating-State/_Index.md +30 -0
- package/second-brain/Shared/Prompting/_Index.md +30 -0
- package/second-brain/Shared/Provenance/_Index.md +30 -0
- package/second-brain/Shared/Rules/_Index.md +30 -0
- package/second-brain/Shared/Rules/contextual-note-rule.md +30 -0
- package/second-brain/Shared/Rules/frontmatter-standard.md +10 -0
- package/second-brain/Shared/Rules/memory-write-protocol.md +28 -0
- package/second-brain/Shared/Rules/procedural-runbook-header.md +40 -0
- package/second-brain/Shared/Rules/review-and-staleness-policy.md +22 -0
- package/second-brain/Shared/Rules/rules-formatting.md +34 -0
- package/second-brain/Shared/Scripts/_Index.md +30 -0
- package/second-brain/Shared/Scripts-Archive/_Index.md +30 -0
- package/second-brain/Shared/Tech-Standards/_Index.md +30 -0
- package/second-brain/Shared/Tech-Standards/verification-standard.md +40 -0
- package/second-brain/Shared/User-Memory/_Index.md +30 -0
- package/second-brain/Shared/User-Persona/_Index.md +30 -0
- package/second-brain/Shared/User-Persona/owner-profile.md +25 -0
- package/second-brain/Shared/Working-Memory/_Index.md +30 -0
- package/second-brain/Shared/_Index.md +30 -0
- package/second-brain/Shared/mcp-servers/_Index.md +30 -0
- package/second-brain/Skills/_Index.md +30 -0
- package/second-brain/Templates/_Index.md +30 -0
- package/second-brain/Templates/bug.md +2 -0
- package/second-brain/Templates/handoff.md +2 -0
- package/second-brain/Templates/session.md +2 -0
- package/second-brain/Tools/_Index.md +30 -0
- package/second-brain/Traces/_Index.md +30 -0
- package/second-brain/Vault Structure Map.md +33 -1
- package/second-brain/copilot/_Index.md +30 -0
- package/skills/audit-license-compliance/SKILL.md +117 -0
- package/skills/author-codemod/SKILL.md +110 -0
- package/skills/build-audit-logging/SKILL.md +112 -0
- package/skills/build-cdc-streaming-pipeline/SKILL.md +123 -0
- package/skills/build-cli-tool/SKILL.md +108 -0
- package/skills/build-data-table/SKILL.md +141 -0
- package/skills/build-native-mobile-ui/SKILL.md +154 -0
- package/skills/build-offline-first-sync/SKILL.md +118 -0
- package/skills/build-realtime-channel/SKILL.md +122 -0
- package/skills/build-vector-search/SKILL.md +131 -0
- package/skills/compose-local-dev-stack/SKILL.md +149 -0
- package/skills/configure-bundler-build/SKILL.md +166 -0
- package/skills/configure-dns-tls/SKILL.md +142 -0
- package/skills/configure-reverse-proxy-lb/SKILL.md +129 -0
- package/skills/configure-security-headers-csp/SKILL.md +122 -0
- package/skills/contract-testing/SKILL.md +140 -0
- package/skills/datetime-timezone-correctness/SKILL.md +125 -0
- package/skills/debug-ci-pipeline-failure/SKILL.md +134 -0
- package/skills/debug-flaky-tests/SKILL.md +128 -0
- package/skills/defend-llm-prompt-injection/SKILL.md +110 -0
- package/skills/deliver-webhooks/SKILL.md +116 -0
- package/skills/design-api-pagination/SKILL.md +144 -0
- package/skills/design-authorization-model/SKILL.md +119 -0
- package/skills/design-backup-dr-recovery/SKILL.md +113 -0
- package/skills/design-event-sourcing-cqrs/SKILL.md +143 -0
- package/skills/design-multi-tenancy/SKILL.md +100 -0
- package/skills/design-protobuf-grpc-service/SKILL.md +146 -0
- package/skills/design-relational-schema/SKILL.md +129 -0
- package/skills/design-search-index-infra/SKILL.md +151 -0
- package/skills/design-state-machine/SKILL.md +108 -0
- package/skills/design-token-system/SKILL.md +109 -0
- package/skills/distributed-locks-leases/SKILL.md +120 -0
- package/skills/encrypt-sensitive-data/SKILL.md +148 -0
- package/skills/feature-flags-rollout/SKILL.md +130 -0
- package/skills/file-upload-object-storage/SKILL.md +107 -0
- package/skills/fuzz-dynamic-security-test/SKILL.md +111 -0
- package/skills/harden-llm-app-reliability/SKILL.md +126 -0
- package/skills/i18n-localization-setup/SKILL.md +113 -0
- package/skills/idempotency-keys/SKILL.md +107 -0
- package/skills/implement-push-notifications/SKILL.md +142 -0
- package/skills/ingest-webhook-secure/SKILL.md +120 -0
- package/skills/integrate-oauth-oidc/SKILL.md +126 -0
- package/skills/load-stress-test/SKILL.md +129 -0
- package/skills/map-privacy-data-gdpr/SKILL.md +146 -0
- package/skills/model-nosql-data/SKILL.md +118 -0
- package/skills/money-decimal-arithmetic/SKILL.md +123 -0
- package/skills/monitor-ml-drift/SKILL.md +109 -0
- package/skills/numeric-precision-units/SKILL.md +144 -0
- package/skills/optimize-llm-cost-latency/SKILL.md +103 -0
- package/skills/optimize-react-rerenders/SKILL.md +124 -0
- package/skills/orchestrate-agent-workflow/SKILL.md +100 -0
- package/skills/payments-billing-integration/SKILL.md +114 -0
- package/skills/pin-toolchain-versions/SKILL.md +116 -0
- package/skills/plan-strangler-migration/SKILL.md +95 -0
- package/skills/property-based-testing/SKILL.md +108 -0
- package/skills/publish-package-registry/SKILL.md +130 -0
- package/skills/recover-git-state/SKILL.md +119 -0
- package/skills/remediate-web-vulnerabilities/SKILL.md +125 -0
- package/skills/resilience-timeouts-retries/SKILL.md +104 -0
- package/skills/resolve-merge-rebase-conflict/SKILL.md +97 -0
- package/skills/rewrite-git-history/SKILL.md +109 -0
- package/skills/scaffold-cross-platform-app/SKILL.md +137 -0
- package/skills/schema-evolution-compatibility/SKILL.md +121 -0
- package/skills/send-transactional-email/SKILL.md +126 -0
- package/skills/serve-deploy-ml-model/SKILL.md +107 -0
- package/skills/setup-cdn-edge-waf/SKILL.md +107 -0
- package/skills/setup-devcontainer-env/SKILL.md +131 -0
- package/skills/setup-lint-format-precommit/SKILL.md +140 -0
- package/skills/setup-monorepo-tooling/SKILL.md +125 -0
- package/skills/ship-mobile-app-store-release/SKILL.md +137 -0
- package/skills/structured-output-llm/SKILL.md +86 -0
- package/skills/supply-chain-sbom-provenance/SKILL.md +120 -0
- package/skills/test-data-factories/SKILL.md +158 -0
- package/skills/threat-model-stride/SKILL.md +123 -0
- package/skills/train-evaluate-ml-model/SKILL.md +109 -0
- package/skills/unicode-text-correctness/SKILL.md +109 -0
- package/skills/visual-regression-testing/SKILL.md +120 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
tags: [index, moc, working-memory]
|
|
3
|
+
note_type: moc
|
|
4
|
+
created: {{DATE}}
|
|
5
|
+
updated: {{DATE}}
|
|
6
|
+
parent: "[[Shared/_Index]]"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Working-Memory
|
|
10
|
+
|
|
11
|
+
> scratchpad ระหว่าง 1 task (ลบทิ้งได้)
|
|
12
|
+
|
|
13
|
+
## ใส่ที่นี่
|
|
14
|
+
ของชั่วคราวระหว่างทำงาน
|
|
15
|
+
|
|
16
|
+
## ไม่ใส่ที่นี่
|
|
17
|
+
อะไรที่จะเก็บ (→Memory-Inbox)
|
|
18
|
+
|
|
19
|
+
## AI Routing Contract
|
|
20
|
+
|
|
21
|
+
- ก่อนเขียน: เช็กว่าเนื้อหาตรง "ใส่ที่นี่" และไม่เข้า "ไม่ใส่ที่นี่"; ถ้าก้ำกึ่งอ่าน [[Vault Structure Map]] ก่อน
|
|
22
|
+
- ก่อนสร้างไฟล์ใหม่: ค้นหาโน้ตเดิมในโฟลเดอร์นี้และโฟลเดอร์ใกล้เคียงก่อน เพื่อ merge/update แทน append ซ้ำ
|
|
23
|
+
- เมื่อสร้างโน้ตในโฟลเดอร์นี้: ตั้ง `parent: "[[Shared/Working-Memory/_Index]]"` และท้ายไฟล์ `up:: [[Shared/Working-Memory/_Index]]`
|
|
24
|
+
- หลังเขียน: เชื่อม link ไป source/project/session/decision ที่เกี่ยวข้อง และอัปเดต hub/index ถ้าโน้ตนี้ควรถูกค้นเจอในอนาคต
|
|
25
|
+
|
|
26
|
+
> รายละเอียดทุกโฟลเดอร์ + decision rules → [[Vault Structure Map]]
|
|
27
|
+
|
|
28
|
+
_(ยังว่าง — โน้ตในโฟลเดอร์นี้จะถูกลิงก์ที่นี่)_
|
|
29
|
+
|
|
30
|
+
up:: [[Shared/_Index]]
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
tags: [index, moc, shared]
|
|
3
|
+
note_type: moc
|
|
4
|
+
created: {{DATE}}
|
|
5
|
+
updated: {{DATE}}
|
|
6
|
+
parent: "[[Home]]"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Shared
|
|
10
|
+
|
|
11
|
+
> สมองกลาง: memory + rules + coordination
|
|
12
|
+
|
|
13
|
+
## ใส่ที่นี่
|
|
14
|
+
เข้าผ่าน AI-Context-Index
|
|
15
|
+
|
|
16
|
+
## ไม่ใส่ที่นี่
|
|
17
|
+
โน้ตงานทั่วไป
|
|
18
|
+
|
|
19
|
+
## AI Routing Contract
|
|
20
|
+
|
|
21
|
+
- ก่อนเขียน: เช็กว่าเนื้อหาตรง "ใส่ที่นี่" และไม่เข้า "ไม่ใส่ที่นี่"; ถ้าก้ำกึ่งอ่าน [[Vault Structure Map]] ก่อน
|
|
22
|
+
- ก่อนสร้างไฟล์ใหม่: ค้นหาโน้ตเดิมในโฟลเดอร์นี้และโฟลเดอร์ใกล้เคียงก่อน เพื่อ merge/update แทน append ซ้ำ
|
|
23
|
+
- เมื่อสร้างโน้ตในโฟลเดอร์นี้: ตั้ง `parent: "[[Shared/_Index]]"` และท้ายไฟล์ `up:: [[Shared/_Index]]`
|
|
24
|
+
- หลังเขียน: เชื่อม link ไป source/project/session/decision ที่เกี่ยวข้อง และอัปเดต hub/index ถ้าโน้ตนี้ควรถูกค้นเจอในอนาคต
|
|
25
|
+
|
|
26
|
+
> รายละเอียดทุกโฟลเดอร์ + decision rules → [[Vault Structure Map]]
|
|
27
|
+
|
|
28
|
+
_(ยังว่าง — โน้ตในโฟลเดอร์นี้จะถูกลิงก์ที่นี่)_
|
|
29
|
+
|
|
30
|
+
up:: [[Home]]
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
tags: [index, moc, mcp-servers]
|
|
3
|
+
note_type: moc
|
|
4
|
+
created: {{DATE}}
|
|
5
|
+
updated: {{DATE}}
|
|
6
|
+
parent: "[[Shared/_Index]]"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# mcp-servers
|
|
10
|
+
|
|
11
|
+
> vendored local MCP server bundle (code/README)
|
|
12
|
+
|
|
13
|
+
## ใส่ที่นี่
|
|
14
|
+
โค้ด/README ของ MCP server (config อยู่ Tech-Standards)
|
|
15
|
+
|
|
16
|
+
## ไม่ใส่ที่นี่
|
|
17
|
+
config การต่อ (→Tech-Standards/mcp.json)
|
|
18
|
+
|
|
19
|
+
## AI Routing Contract
|
|
20
|
+
|
|
21
|
+
- ก่อนเขียน: เช็กว่าเนื้อหาตรง "ใส่ที่นี่" และไม่เข้า "ไม่ใส่ที่นี่"; ถ้าก้ำกึ่งอ่าน [[Vault Structure Map]] ก่อน
|
|
22
|
+
- ก่อนสร้างไฟล์ใหม่: ค้นหาโน้ตเดิมในโฟลเดอร์นี้และโฟลเดอร์ใกล้เคียงก่อน เพื่อ merge/update แทน append ซ้ำ
|
|
23
|
+
- เมื่อสร้างโน้ตในโฟลเดอร์นี้: ตั้ง `parent: "[[Shared/mcp-servers/_Index]]"` และท้ายไฟล์ `up:: [[Shared/mcp-servers/_Index]]`
|
|
24
|
+
- หลังเขียน: เชื่อม link ไป source/project/session/decision ที่เกี่ยวข้อง และอัปเดต hub/index ถ้าโน้ตนี้ควรถูกค้นเจอในอนาคต
|
|
25
|
+
|
|
26
|
+
> รายละเอียดทุกโฟลเดอร์ + decision rules → [[Vault Structure Map]]
|
|
27
|
+
|
|
28
|
+
_(ยังว่าง — โน้ตในโฟลเดอร์นี้จะถูกลิงก์ที่นี่)_
|
|
29
|
+
|
|
30
|
+
up:: [[Shared/_Index]]
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
tags: [index, moc, skills]
|
|
3
|
+
note_type: moc
|
|
4
|
+
created: {{DATE}}
|
|
5
|
+
updated: {{DATE}}
|
|
6
|
+
parent: "[[Home]]"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Skills
|
|
10
|
+
|
|
11
|
+
> reusable unit ที่ executable + ผ่าน verification command
|
|
12
|
+
|
|
13
|
+
## ใส่ที่นี่
|
|
14
|
+
script/command ที่รัน test ผ่าน (ดู Shared/Rules/skills-admission)
|
|
15
|
+
|
|
16
|
+
## ไม่ใส่ที่นี่
|
|
17
|
+
prose how-to (→Runbooks) · unverified (→Memory-Inbox)
|
|
18
|
+
|
|
19
|
+
## AI Routing Contract
|
|
20
|
+
|
|
21
|
+
- ก่อนเขียน: เช็กว่าเนื้อหาตรง "ใส่ที่นี่" และไม่เข้า "ไม่ใส่ที่นี่"; ถ้าก้ำกึ่งอ่าน [[Vault Structure Map]] ก่อน
|
|
22
|
+
- ก่อนสร้างไฟล์ใหม่: ค้นหาโน้ตเดิมในโฟลเดอร์นี้และโฟลเดอร์ใกล้เคียงก่อน เพื่อ merge/update แทน append ซ้ำ
|
|
23
|
+
- เมื่อสร้างโน้ตในโฟลเดอร์นี้: ตั้ง `parent: "[[Skills/_Index]]"` และท้ายไฟล์ `up:: [[Skills/_Index]]`
|
|
24
|
+
- หลังเขียน: เชื่อม link ไป source/project/session/decision ที่เกี่ยวข้อง และอัปเดต hub/index ถ้าโน้ตนี้ควรถูกค้นเจอในอนาคต
|
|
25
|
+
|
|
26
|
+
> รายละเอียดทุกโฟลเดอร์ + decision rules → [[Vault Structure Map]]
|
|
27
|
+
|
|
28
|
+
_(ยังว่าง — โน้ตในโฟลเดอร์นี้จะถูกลิงก์ที่นี่)_
|
|
29
|
+
|
|
30
|
+
up:: [[Home]]
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
tags: [index, moc, templates]
|
|
3
|
+
note_type: moc
|
|
4
|
+
created: {{DATE}}
|
|
5
|
+
updated: {{DATE}}
|
|
6
|
+
parent: "[[Home]]"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Templates
|
|
10
|
+
|
|
11
|
+
> แม่แบบโน้ต — instantiate จากที่นี่
|
|
12
|
+
|
|
13
|
+
## ใส่ที่นี่
|
|
14
|
+
template ไว้ instantiate (session/bug/handoff/project)
|
|
15
|
+
|
|
16
|
+
## ไม่ใส่ที่นี่
|
|
17
|
+
โน้ตจริง
|
|
18
|
+
|
|
19
|
+
## AI Routing Contract
|
|
20
|
+
|
|
21
|
+
- ก่อนเขียน: เช็กว่าเนื้อหาตรง "ใส่ที่นี่" และไม่เข้า "ไม่ใส่ที่นี่"; ถ้าก้ำกึ่งอ่าน [[Vault Structure Map]] ก่อน
|
|
22
|
+
- ก่อนสร้างไฟล์ใหม่: ค้นหาโน้ตเดิมในโฟลเดอร์นี้และโฟลเดอร์ใกล้เคียงก่อน เพื่อ merge/update แทน append ซ้ำ
|
|
23
|
+
- เมื่อสร้างโน้ตในโฟลเดอร์นี้: ตั้ง `parent: "[[Templates/_Index]]"` และท้ายไฟล์ `up:: [[Templates/_Index]]`
|
|
24
|
+
- หลังเขียน: เชื่อม link ไป source/project/session/decision ที่เกี่ยวข้อง และอัปเดต hub/index ถ้าโน้ตนี้ควรถูกค้นเจอในอนาคต
|
|
25
|
+
|
|
26
|
+
> รายละเอียดทุกโฟลเดอร์ + decision rules → [[Vault Structure Map]]
|
|
27
|
+
|
|
28
|
+
_(ยังว่าง — โน้ตในโฟลเดอร์นี้จะถูกลิงก์ที่นี่)_
|
|
29
|
+
|
|
30
|
+
up:: [[Home]]
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
tags: [index, moc, tools]
|
|
3
|
+
note_type: moc
|
|
4
|
+
created: {{DATE}}
|
|
5
|
+
updated: {{DATE}}
|
|
6
|
+
parent: "[[Home]]"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Tools
|
|
10
|
+
|
|
11
|
+
> utility/tooling เฉพาะเครื่องหรือเฉพาะ vault
|
|
12
|
+
|
|
13
|
+
## ใส่ที่นี่
|
|
14
|
+
local helper, binary wrapper, one-off utility ที่ยังใช้อยู่
|
|
15
|
+
|
|
16
|
+
## ไม่ใส่ที่นี่
|
|
17
|
+
durable knowledge (→Learning/Runbooks) · verified executable skill (→Skills)
|
|
18
|
+
|
|
19
|
+
## AI Routing Contract
|
|
20
|
+
|
|
21
|
+
- ก่อนเขียน: เช็กว่าเนื้อหาตรง "ใส่ที่นี่" และไม่เข้า "ไม่ใส่ที่นี่"; ถ้าก้ำกึ่งอ่าน [[Vault Structure Map]] ก่อน
|
|
22
|
+
- ก่อนสร้างไฟล์ใหม่: ค้นหาโน้ตเดิมในโฟลเดอร์นี้และโฟลเดอร์ใกล้เคียงก่อน เพื่อ merge/update แทน append ซ้ำ
|
|
23
|
+
- เมื่อสร้างโน้ตในโฟลเดอร์นี้: ตั้ง `parent: "[[Tools/_Index]]"` และท้ายไฟล์ `up:: [[Tools/_Index]]`
|
|
24
|
+
- หลังเขียน: เชื่อม link ไป source/project/session/decision ที่เกี่ยวข้อง และอัปเดต hub/index ถ้าโน้ตนี้ควรถูกค้นเจอในอนาคต
|
|
25
|
+
|
|
26
|
+
> รายละเอียดทุกโฟลเดอร์ + decision rules → [[Vault Structure Map]]
|
|
27
|
+
|
|
28
|
+
_(ยังว่าง — โน้ตในโฟลเดอร์นี้จะถูกลิงก์ที่นี่)_
|
|
29
|
+
|
|
30
|
+
up:: [[Home]]
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
tags: [index, moc, traces]
|
|
3
|
+
note_type: moc
|
|
4
|
+
created: {{DATE}}
|
|
5
|
+
updated: {{DATE}}
|
|
6
|
+
parent: "[[Home]]"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Traces
|
|
10
|
+
|
|
11
|
+
> exploration/reasoning chain ยาว
|
|
12
|
+
|
|
13
|
+
## ใส่ที่นี่
|
|
14
|
+
การสืบสวนหลายขั้น (คำถามใหญ่เกินโน้ตเดียว)
|
|
15
|
+
|
|
16
|
+
## ไม่ใส่ที่นี่
|
|
17
|
+
คำตอบสั้น (→โน้ตปกติ)
|
|
18
|
+
|
|
19
|
+
## AI Routing Contract
|
|
20
|
+
|
|
21
|
+
- ก่อนเขียน: เช็กว่าเนื้อหาตรง "ใส่ที่นี่" และไม่เข้า "ไม่ใส่ที่นี่"; ถ้าก้ำกึ่งอ่าน [[Vault Structure Map]] ก่อน
|
|
22
|
+
- ก่อนสร้างไฟล์ใหม่: ค้นหาโน้ตเดิมในโฟลเดอร์นี้และโฟลเดอร์ใกล้เคียงก่อน เพื่อ merge/update แทน append ซ้ำ
|
|
23
|
+
- เมื่อสร้างโน้ตในโฟลเดอร์นี้: ตั้ง `parent: "[[Traces/_Index]]"` และท้ายไฟล์ `up:: [[Traces/_Index]]`
|
|
24
|
+
- หลังเขียน: เชื่อม link ไป source/project/session/decision ที่เกี่ยวข้อง และอัปเดต hub/index ถ้าโน้ตนี้ควรถูกค้นเจอในอนาคต
|
|
25
|
+
|
|
26
|
+
> รายละเอียดทุกโฟลเดอร์ + decision rules → [[Vault Structure Map]]
|
|
27
|
+
|
|
28
|
+
_(ยังว่าง — โน้ตในโฟลเดอร์นี้จะถูกลิงก์ที่นี่)_
|
|
29
|
+
|
|
30
|
+
up:: [[Home]]
|
|
@@ -20,15 +20,22 @@ ai_surface: hot
|
|
|
20
20
|
| log งานที่ทำ | `Sessions/` | `YYYY-MM-DD-<topic>.md` |
|
|
21
21
|
| preference ของเจ้าของ | `Shared/User-Memory/` | |
|
|
22
22
|
| การตัดสินใจสำคัญ | `Shared/Decision-Memory/` | |
|
|
23
|
+
| priority/current focus เปลี่ยน | `Shared/Operating-State/current-state.md` | update existing |
|
|
23
24
|
| ยังไม่ชัด/ขัดกัน | `Shared/Memory-Inbox/` | |
|
|
24
25
|
| content จากเว็บ/paste | `Intake/_Quarantine/` | (scan ก่อน) |
|
|
25
26
|
| ต้นฉบับดิบ read-only | `Intake/Raw Sources/` | |
|
|
27
|
+
| finding ที่มี source | `Research/` | ใส่ `source::` |
|
|
28
|
+
| scratch ชั่วคราวระหว่างงาน | `Shared/Working-Memory/` | ลบทิ้ง/โปรโมทหลังจบ |
|
|
26
29
|
| script ที่ผ่าน test | `Skills/` | |
|
|
27
30
|
| how-to อ่านแล้วทำเอง | `Runbooks/` | |
|
|
28
31
|
| กลยุทธ์ที่ปรับดีขึ้น | `Playbooks/` | |
|
|
32
|
+
| fixture expected output | `Acceptance/` | input→expected |
|
|
33
|
+
| pre/postflight gate | `Checklists/` | ticklist |
|
|
29
34
|
| page ของคน/องค์กร/concept | `Entities/` | |
|
|
30
35
|
| bug | `Bugs/` | `YYYY-MM-DD-<bug>.md` |
|
|
36
|
+
| bug ระบบ/OS/toolchain | `Bugs/System-OS/` | `YYYY-MM-DD-<bug>.md` |
|
|
31
37
|
| ส่งมอบงานค้าง | `Handoffs/` | |
|
|
38
|
+
| multi-agent task card | `Shared/Coordination/task-board/` | `<id>.md` |
|
|
32
39
|
|
|
33
40
|
## §2 Full Reference (ครบทุกโฟลเดอร์ — ใส่อะไร / ห้ามใส่)
|
|
34
41
|
|
|
@@ -44,6 +51,7 @@ ai_surface: hot
|
|
|
44
51
|
| `Runbooks/` | prose how-to | ขั้นตอน setup/deploy/maintain | runnable unit (→Skills) |
|
|
45
52
|
| `Templates/` | แม่แบบโน้ต | template ไว้ instantiate | โน้ตจริง |
|
|
46
53
|
| `Bugs/` | bug reproducible (global flat) | bug report + link กลับ project | bug ของ project ที่ไม่ reproduce |
|
|
54
|
+
| `Bugs/System-OS/` | bug ระบบ/OS/toolchain | OS, shell, package manager, permission, filesystem, app-runtime bugs | bug ของ project เฉพาะ |
|
|
47
55
|
| `Handoffs/` | ส่งมอบงานค้าง (snapshot) | state + next steps ส่งต่อ | live coordination (→Coordination) |
|
|
48
56
|
|
|
49
57
|
### Direction
|
|
@@ -81,13 +89,35 @@ ai_surface: hot
|
|
|
81
89
|
| `Shared/Decision-Memory/` | decision ที่ AI บันทึก | decision locked + supersedes | ground truth คน (→Core-Facts) |
|
|
82
90
|
| `Shared/Memory-Inbox/` | candidate ยังไม่ชัด | observation รอ promote (clear weekly) | durable ที่ชัดแล้ว (→ปลายทาง) |
|
|
83
91
|
| `Shared/Rules/` | กฎ operating always-on | memory/frontmatter/context-assembly | how-to ทำงาน (→Runbooks) |
|
|
84
|
-
| `Shared/Tech-Standards/` | มาตรฐานเทคนิค | MCP/stack/DoD/verification | |
|
|
92
|
+
| `Shared/Tech-Standards/` | มาตรฐานเทคนิค | MCP/stack/DoD/verification | กฎ memory/format (→Rules) |
|
|
85
93
|
| `Shared/Core-Facts/` | ground truth คนเขียน (read-only) | invariant ที่ AI ห้ามแก้ | decision ที่ AI ตัด (→Decision-Memory) |
|
|
86
94
|
| `Shared/Coordination/` | live multi-agent baton | NOW.md + task-board + registry | เอกสารส่งมอบ (→Handoffs) |
|
|
95
|
+
| `Shared/Coordination/task-board/` | file-Kanban task cards | task ต่อชิ้นงาน มี `claimed_by`/`status` | session narrative หรือ handoff snapshot |
|
|
87
96
|
| `Shared/Working-Memory/` | scratchpad 1 task (ลบได้) | ของชั่วคราวระหว่างทำงาน | อะไรที่จะเก็บ (→Memory-Inbox) |
|
|
88
97
|
| `Shared/User-Persona/` | identity static (read-only) | บทบาท/ค่านิยม/ภาษา/timezone | สิ่งที่ AI เรียนรู้ (→User-Memory) |
|
|
89
98
|
| `Shared/Provenance/` | source ledger | บรรทัด ingest ต่อแหล่ง | โน้ต derived (ใส่ `source::` แทน) |
|
|
90
99
|
| `Shared/Archive/` | cold storage (ไม่ลบ) | โน้ต stale/retired ออกจาก retrieval | ของที่ยังใช้ |
|
|
100
|
+
| `Shared/Scripts/` | automation maintenance | lint/graph-audit/metrics script | one-off retired (→Scripts-Archive) |
|
|
101
|
+
| `Shared/Scripts-Archive/` | สคริปต์ one-off retired | script เก่า (ประวัติ) | script ที่ยังใช้ (→Scripts) |
|
|
102
|
+
| `Shared/mcp-servers/` | vendored MCP server bundle | code/README ของ MCP server | config การต่อ (→Tech-Standards) |
|
|
103
|
+
| `Shared/Context-Packs/` | full-context bundle | pack รวม context พร้อมโหลด | โน้ตเดี่ยว |
|
|
104
|
+
| `Shared/Context7-Docs/` | cached lib doc (regenerable) | cache context7/lib doc | durable knowledge (→Learning) |
|
|
105
|
+
| `Shared/AI-Threads/` | saved AI reasoning trail | thread review/resume/promote | durable decision (→Decision-Memory) |
|
|
106
|
+
| `Shared/Prompting/` | prompt-engineering pattern | pattern การเขียน prompt | prompt asset (→Prompts) |
|
|
107
|
+
| `Shared/Glossary/` | vocabulary กลาง | term + นิยาม | entity page (→Entities) |
|
|
108
|
+
| `Shared/Assets/` | รูป/logo/binary | image/logo/asset | โน้ต .md |
|
|
109
|
+
|
|
110
|
+
### AI agent config / vendor (root-level)
|
|
111
|
+
| Folder | Role | ใส่ที่นี่ | ห้ามใส่ |
|
|
112
|
+
|---|---|---|---|
|
|
113
|
+
| `.agents/` `.agents/skills/` | skill folders (SKILL.md) | SKILL.md ที่ agent โหลด on-demand | prose how-to (→Runbooks) |
|
|
114
|
+
| `.agents/workflows/` | workflow guides | multi-step orchestration ที่ทำซ้ำ | one-off task |
|
|
115
|
+
| `copilot/` | vendor export (review/promote) | export จาก Copilot | durable (promote เข้า durable layer) |
|
|
116
|
+
|
|
117
|
+
### Optional / Machine-local
|
|
118
|
+
| Folder | Role | ใส่ที่นี่ | ห้ามใส่ |
|
|
119
|
+
|---|---|---|---|
|
|
120
|
+
| `Tools/` | utility เฉพาะเครื่อง/vault | local helper, wrapper, utility ที่ยังใช้ | durable knowledge หรือ verified skill |
|
|
91
121
|
|
|
92
122
|
## §3 Decision Rules (เคสกำกวม)
|
|
93
123
|
|
|
@@ -98,6 +128,8 @@ ai_surface: hot
|
|
|
98
128
|
- **sourced vs self-derived:** มี external source→`Research` · กลั่นเอง→`Learning`
|
|
99
129
|
- **finite vs ongoing:** มีวันจบ→`Goals` · ไม่จบ→`Areas`
|
|
100
130
|
- **event vs cadence vs metric:** หลังงาน→`Retrospectives` · ตามรอบ→`Reviews` · วัดคุณภาพ→`Evals`
|
|
131
|
+
- **system bug vs project bug:** OS/toolchain/runtime กว้างๆ→`Bugs/System-OS` · bug ของงานหนึ่ง→`Bugs`/`Projects/<proj>`
|
|
132
|
+
- **coordination task vs narrative:** claimable task card→`Shared/Coordination/task-board` · เล่า session→`Sessions` · ส่งต่อ state→`Handoffs`
|
|
101
133
|
|
|
102
134
|
## §4 Footer
|
|
103
135
|
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
tags: [index, moc, copilot]
|
|
3
|
+
note_type: moc
|
|
4
|
+
created: {{DATE}}
|
|
5
|
+
updated: {{DATE}}
|
|
6
|
+
parent: "[[Home]]"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# copilot
|
|
10
|
+
|
|
11
|
+
> vendor export (conversation/custom-prompt/memory snapshot) — review/promote, ไม่ใช่ source of truth
|
|
12
|
+
|
|
13
|
+
## ใส่ที่นี่
|
|
14
|
+
export จาก Copilot ที่เก็บใน-vault
|
|
15
|
+
|
|
16
|
+
## ไม่ใส่ที่นี่
|
|
17
|
+
durable (promote เข้า durable layer)
|
|
18
|
+
|
|
19
|
+
## AI Routing Contract
|
|
20
|
+
|
|
21
|
+
- ก่อนเขียน: เช็กว่าเนื้อหาตรง "ใส่ที่นี่" และไม่เข้า "ไม่ใส่ที่นี่"; ถ้าก้ำกึ่งอ่าน [[Vault Structure Map]] ก่อน
|
|
22
|
+
- ก่อนสร้างไฟล์ใหม่: ค้นหาโน้ตเดิมในโฟลเดอร์นี้และโฟลเดอร์ใกล้เคียงก่อน เพื่อ merge/update แทน append ซ้ำ
|
|
23
|
+
- เมื่อสร้างโน้ตในโฟลเดอร์นี้: ตั้ง `parent: "[[copilot/_Index]]"` และท้ายไฟล์ `up:: [[copilot/_Index]]`
|
|
24
|
+
- หลังเขียน: เชื่อม link ไป source/project/session/decision ที่เกี่ยวข้อง และอัปเดต hub/index ถ้าโน้ตนี้ควรถูกค้นเจอในอนาคต
|
|
25
|
+
|
|
26
|
+
> รายละเอียดทุกโฟลเดอร์ + decision rules → [[Vault Structure Map]]
|
|
27
|
+
|
|
28
|
+
_(ยังว่าง — โน้ตในโฟลเดอร์นี้จะถูกลิงก์ที่นี่)_
|
|
29
|
+
|
|
30
|
+
up:: [[Home]]
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: audit-license-compliance
|
|
3
|
+
description: Audits open-source license compliance — resolves SPDX identifiers across the full transitive dependency tree (license-checker/scancode), classifies copyleft (GPL/AGPL/LGPL) exposure against the distribution model, enforces an allow/deny CI policy, and generates NOTICE/THIRD-PARTY attribution files.
|
|
4
|
+
when_to_use: Shipping a product/library or prepping a legal/procurement review and needing to clear OSS license obligations. Distinct from supply-chain-sbom-provenance (build integrity, SBOM signing, provenance), dependency-upgrade (version bumps), and publish-package-registry (the publish step).
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## When to Use
|
|
8
|
+
|
|
9
|
+
Reach for this skill when the question is about **license obligations**, not which versions to ship or whether the build is tamper-proof:
|
|
10
|
+
|
|
11
|
+
- "Can we ship — does anything here have a GPL/AGPL problem?"
|
|
12
|
+
- "Generate the NOTICE / THIRD-PARTY-LICENSES file for the release."
|
|
13
|
+
- "Add a CI gate that fails the build on a forbidden license."
|
|
14
|
+
- "Legal/procurement needs the full list of dependencies and their licenses."
|
|
15
|
+
- "This transitive dep has no license / is dual-licensed — what do we do?"
|
|
16
|
+
- "We're going from internal SaaS to a downloadable binary — what changes?"
|
|
17
|
+
|
|
18
|
+
NOT this skill:
|
|
19
|
+
- Generating/signing an SBOM, provenance, or attestations → supply-chain-sbom-provenance (it lists *components*; this skill judges their *licenses*)
|
|
20
|
+
- Bumping a version or swapping a GPL dep for an alternative → dependency-upgrade
|
|
21
|
+
- The actual `npm publish` / `twine upload` step and its OIDC gate → publish-package-registry
|
|
22
|
+
- A design-level risk enumeration of the system → threat-model-stride
|
|
23
|
+
|
|
24
|
+
## Steps
|
|
25
|
+
|
|
26
|
+
1. **Scan the FULL transitive tree, not just direct deps — and pin the result to a manifest.** Direct deps are a tiny minority; copyleft almost always rides in transitively. Pick the resolver for the ecosystem and emit machine-readable output:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# Node — license-checker-rseki (maintained fork) over the *production* tree only
|
|
30
|
+
npx license-checker-rseki --production --json --out licenses.json
|
|
31
|
+
# Python
|
|
32
|
+
pip-licenses --format=json --with-license-file --with-urls > licenses.json
|
|
33
|
+
# Rust
|
|
34
|
+
cargo install cargo-deny && cargo deny list -f json > licenses.json
|
|
35
|
+
# Go
|
|
36
|
+
go install github.com/google/go-licenses@latest && go-licenses report ./... > licenses.csv
|
|
37
|
+
# Ground truth when metadata lies — scans actual file headers/text
|
|
38
|
+
pipx run scancode-toolkit scancode --license --json-pp scancode.json <vendored_dir>
|
|
39
|
+
```
|
|
40
|
+
Scope to what you **distribute**: prod/runtime deps only. devDependencies, test, and build-only tooling are generally not distributed — exclude them (`--production`, `--omit=dev`) or you'll drown in false GPL hits from linters. When package metadata is missing or wrong, `scancode` reading the real LICENSE/headers is the tiebreaker, not the `package.json` `license` field.
|
|
41
|
+
|
|
42
|
+
2. **Classify each license by risk against YOUR distribution model — this is the whole audit.** The same license is fine or fatal depending on how you ship. Decide the model first, then read the table left-to-right:
|
|
43
|
+
|
|
44
|
+
| License class | Examples | SaaS (network only) | Distributed binary / app | Library you publish |
|
|
45
|
+
|---|---|---|---|---|
|
|
46
|
+
| Permissive | MIT, BSD-2/3, ISC, Apache-2.0, Unlicense, 0BSD | ✅ allow | ✅ allow (must keep NOTICE) | ✅ allow |
|
|
47
|
+
| Weak copyleft (file) | MPL-2.0, EPL-2.0, CDDL | ✅ allow | ⚠️ allow if unmodified & file-isolated | ⚠️ review |
|
|
48
|
+
| Weak copyleft (lib) | LGPL-2.1/3.0 | ✅ allow | ⚠️ **dynamic** link only; static link triggers relink obligation | ⚠️ review |
|
|
49
|
+
| Strong copyleft | GPL-2.0, GPL-3.0 | ✅ allow (no conveying) | ❌ **deny** — forces whole-program source disclosure | ❌ deny |
|
|
50
|
+
| Network copyleft | **AGPL-3.0** | ❌ **deny** — network use = conveying, source must be offered to users | ❌ deny | ❌ deny |
|
|
51
|
+
| Notice-heavy / patent | Apache-2.0, BSD-4-Clause | ✅ (track NOTICE/patent grant) | ⚠️ BSD-4 advertising clause incompatible w/ GPL | ⚠️ review |
|
|
52
|
+
| Non-OSS / source-available | SSPL, BUSL-1.1, Elastic-2.0, CC-BY-NC, "Commons Clause" | ❌ deny (not OSI; usage-restricted) | ❌ deny | ❌ deny |
|
|
53
|
+
| Public domain / unclear | WTFPL, "UNLICENSED", no license | ❌ deny pending manual review | ❌ deny pending review | ❌ deny |
|
|
54
|
+
|
|
55
|
+
The trap most teams miss: **AGPL bites SaaS** (where GPL does not, because you never "convey" a binary), and **LGPL/GPL bite distributed binaries** (where they're harmless on a server). Set the model once; don't hand-wave it as "it depends."
|
|
56
|
+
|
|
57
|
+
3. **Encode the policy as allow / deny / review with SPDX IDs and gate CI on it.** A human-readable table isn't enforcement. Use one tool to both classify and fail the build. `cargo-deny`-style config (mirror the shape in `license-checker --failOn` or an `oss-review-toolkit`/`fossa`/`trivy` policy):
|
|
58
|
+
|
|
59
|
+
```toml
|
|
60
|
+
# deny.toml — explicit allowlist; everything unlisted is a hard failure
|
|
61
|
+
[licenses]
|
|
62
|
+
allow = ["MIT", "Apache-2.0", "BSD-2-Clause", "BSD-3-Clause", "ISC", "MPL-2.0"]
|
|
63
|
+
confidence-threshold = 0.9 # below this, treat as unknown → fail
|
|
64
|
+
|
|
65
|
+
# exceptions: this one crate is allowed despite the policy, with a reason on record
|
|
66
|
+
[[licenses.exceptions]]
|
|
67
|
+
crate = "ring"
|
|
68
|
+
allow = ["OpenSSL"] # rationale: leaf TLS dep, OpenSSL terms cleared by legal 2026-05
|
|
69
|
+
```
|
|
70
|
+
```bash
|
|
71
|
+
# CI gate — non-zero exit blocks the merge. Run on every PR.
|
|
72
|
+
cargo deny check licenses
|
|
73
|
+
# Node equivalent (allowlist must match deny.toml above):
|
|
74
|
+
npx license-checker-rseki --production --onlyAllow \
|
|
75
|
+
"MIT;Apache-2.0;BSD-2-Clause;BSD-3-Clause;ISC;MPL-2.0" --excludePrivatePackages
|
|
76
|
+
```
|
|
77
|
+
Default posture is **allowlist, deny-by-default**: an unknown/unparseable license fails closed, so a newly added denied or no-license dep cannot merge silently. Route genuinely-ambiguous cases to a `review` bucket that fails CI with a "needs legal sign-off" message rather than auto-allowing.
|
|
78
|
+
|
|
79
|
+
4. **Resolve dual-licensed and missing-license deps explicitly — never let the tool pick for you.** SPDX `OR` means *you choose* (e.g. `(MIT OR Apache-2.0)` → pick the one in your allowlist and record the choice). SPDX `AND` means *both apply* (you must satisfy every obligation). For a dep with **no license**, default-deny: open an issue, contact the maintainer, or remove it — "no license" means all-rights-reserved, not free. Pin every resolution and exception in `deny.toml`/policy with a one-line rationale so the next audit doesn't relitigate it.
|
|
80
|
+
|
|
81
|
+
5. **Generate NOTICE / THIRD-PARTY-LICENSES attribution from the same scan.** Permissive licenses (MIT/BSD/Apache) require you to reproduce their copyright + license text in distributed artifacts; Apache-2.0 also requires propagating any upstream `NOTICE`. Auto-generate, don't hand-maintain:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
npx oss-attribution-generator ./ # → oss-attribution/attribution.txt
|
|
85
|
+
# or: license-checker-rseki --production --customPath fields.json --files THIRD-PARTY-LICENSES/
|
|
86
|
+
pip-licenses --format=plain-vertical --with-license-file --no-license-path \
|
|
87
|
+
--output-file THIRD-PARTY-LICENSES.txt
|
|
88
|
+
go-licenses save ./... --save_path=THIRD-PARTY-LICENSES/
|
|
89
|
+
```
|
|
90
|
+
Ship `THIRD-PARTY-LICENSES.txt` (or `NOTICE`) inside the artifact — in the package tarball, the container image, the app's "Licenses" screen, or `/licenses`. Regenerate it in CI from the locked tree and **diff against the committed copy** so a new dep can't slip in without its attribution.
|
|
91
|
+
|
|
92
|
+
6. **Wire both gates into one CI job.** Policy check (step 3) + attribution drift check (step 5) run on every PR and on the release tag. Fail the build if a denied/unknown license appears OR the generated NOTICE differs from the committed one. This is what makes the audit durable instead of a one-time spreadsheet.
|
|
93
|
+
|
|
94
|
+
## Common Errors
|
|
95
|
+
|
|
96
|
+
- **Scanning direct deps only.** The GPL/AGPL almost always arrives 3 levels deep. Always resolve the full transitive tree (`--production` flattens it).
|
|
97
|
+
- **Including devDependencies in the distributed verdict.** A GPL linter or test runner isn't distributed and isn't a violation — it just floods the report and gets the gate disabled. Scope to runtime/prod.
|
|
98
|
+
- **Trusting the package `license` field over the actual files.** Metadata is frequently wrong, stale, or `SEE LICENSE IN ...`. When it matters, let `scancode` read the real LICENSE/headers; that's ground truth.
|
|
99
|
+
- **Treating AGPL like GPL for a SaaS.** AGPL's network clause means serving it over HTTP *is* conveying — source must be offered to every user. Deny AGPL even when GPL would be fine for your server-only model.
|
|
100
|
+
- **Static-linking an LGPL library into a shipped binary.** That triggers the relink obligation (users must be able to swap the lib). Dynamic-link it, or treat it as deny for static builds.
|
|
101
|
+
- **Auto-picking a side of a dual license silently.** `(GPL-2.0 OR MIT)` is only safe because *you* elect MIT — record the election. If the tool defaulted to GPL, you may have manufactured an obligation that didn't exist.
|
|
102
|
+
- **"No license" read as permissive.** Absence of a license = all rights reserved = you have no grant to use it. Default-deny and resolve, don't ship.
|
|
103
|
+
- **Allowlist that fails *open* on unknowns.** A typo SPDX id or low-confidence match must fail the build, not pass. Set `confidence-threshold` and deny-by-default.
|
|
104
|
+
- **Hand-maintaining NOTICE.** It drifts the moment a transitive dep changes. Generate it from the lockfile in CI and diff against the committed copy.
|
|
105
|
+
- **Confusing source-available with open-source.** SSPL/BUSL/Elastic-2.0/"Commons Clause" are usage-restricted and not OSI-approved — deny them unless legal explicitly cleared the specific use.
|
|
106
|
+
|
|
107
|
+
## Verify
|
|
108
|
+
|
|
109
|
+
1. **Coverage:** The scan output lists *transitive* deps, not just the handful in `package.json`/`Cargo.toml`. Spot-check a known deep dep appears with a license.
|
|
110
|
+
2. **Policy gate fires (positive control):** Add a dep with a denied license (e.g. a GPL-3.0 package) on a throwaway branch → CI **fails** with a message naming the dep and its license. Revert.
|
|
111
|
+
3. **Unknown fails closed:** Point the scanner at a dep with a stripped/garbled license → it is reported as unknown and the gate **fails**, not passes.
|
|
112
|
+
4. **Distribution-model correctness:** Re-run classification under the other model (flip SaaS↔distributed) and confirm AGPL/LGPL/GPL verdicts change as the table predicts — proves the model is actually driving the verdict, not hardcoded.
|
|
113
|
+
5. **Attribution completeness:** Every distributed (prod) dependency in the lockfile appears in `THIRD-PARTY-LICENSES`/`NOTICE` with its license text. Count of attributed deps == count of distributed deps; no entry is empty.
|
|
114
|
+
6. **Attribution drift gate:** Add a prod dep without regenerating → CI's NOTICE-diff check **fails**. Regenerate → it passes and the new dep+license is present.
|
|
115
|
+
7. **Dual/missing resolved:** No dep is left with an unresolved `OR` expression or empty license; each exception in the policy has a written rationale.
|
|
116
|
+
|
|
117
|
+
Done = the scan covers the full transitive prod tree, CI blocks a newly added denied-license **and** an unknown-license dep (verified by positive controls), every distributed dependency is listed with its license in the committed NOTICE, and the NOTICE-drift gate fails when that list goes stale.
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: author-codemod
|
|
3
|
+
description: Writes, fixture-tests, and runs codebase-wide automated transforms (codemods) that parse source to an AST and rewrite nodes via grammar-aware tools (jscodeshift/ts-morph, ast-grep, Comby, libcst/Bowler, OpenRewrite), dry-running before applying one mechanical change across many files. Use when a structural edit must hit many call sites reliably and find-replace would mangle strings, comments, or shadowed names.
|
|
4
|
+
when_to_use: One mechanical change must land across many files — rename/move an exported API across all call sites, swap a deprecated call, rewrite an import path or signature, migrate an idiom (callbacks→async, class→hooks). Distinct from refactor-cleanup (judgment-driven edits in a few files), dependency-upgrade (bumping versions), and regex-build (a single pattern, not a tree transform).
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## When to Use
|
|
8
|
+
|
|
9
|
+
Reach for this skill when the **same structural edit must hit many files** and correctness depends on understanding the code's grammar, not its text:
|
|
10
|
+
|
|
11
|
+
- "Rename `getUser` → `fetchUser` everywhere, including imports/exports/JSX, but not the string `"getUser"` in logs"
|
|
12
|
+
- "Replace every `moment(x)` with `dayjs(x)` across the repo"
|
|
13
|
+
- "Change the import path `@old/pkg` → `@new/pkg` and rewrite the now-renamed named exports"
|
|
14
|
+
- "Migrate all `React.Component` classes to function components / hooks"
|
|
15
|
+
- "Add `await` to every call site of a function that became async"
|
|
16
|
+
- "Swap deprecated `assert.equal` → `assert.strictEqual` repo-wide"
|
|
17
|
+
|
|
18
|
+
NOT this skill:
|
|
19
|
+
- A judgment-heavy cleanup in 1–3 files where each edit is a decision, not a rule → refactor-cleanup
|
|
20
|
+
- Bumping a package version and fixing the fallout it causes → dependency-upgrade (a codemod may be a *step* inside it)
|
|
21
|
+
- One search/replace pattern over text where a tree isn't needed → regex-build
|
|
22
|
+
- Reviewing the resulting diff for bugs → code-review
|
|
23
|
+
- Schema/data changes in a running DB → db-migration-safety
|
|
24
|
+
|
|
25
|
+
## Steps
|
|
26
|
+
|
|
27
|
+
1. **Pick the tool by language and edit shape — don't reach for `sed`.** A grammar-aware tool refuses to touch strings, comments, and shadowed bindings; text tools can't tell them apart.
|
|
28
|
+
|
|
29
|
+
| Language / scope | Tool | Reach for it when |
|
|
30
|
+
|---|---|---|
|
|
31
|
+
| JS/TS, complex semantic rewrite | **jscodeshift** (Babel/recast AST) | rename across imports/exports/JSX, signature changes; preserves formatting via recast |
|
|
32
|
+
| TS, type-aware, follow references | **ts-morph** | needs the type checker — find *all* references to a symbol, not name matches |
|
|
33
|
+
| JS/TS/Go/Python/Rust, pattern→pattern | **ast-grep** (`sg`) | declarative `pattern:`/`rewrite:` in YAML, polyglot, fast, no JS to write |
|
|
34
|
+
| Any language, structural find/replace | **Comby** | lightweight `:[hole]` matchers when you don't want a full AST pass |
|
|
35
|
+
| Python | **libcst** (or **Bowler** for simple cases) | preserves comments + formatting; libcst for graph-aware, Bowler for fluent one-liners |
|
|
36
|
+
| Java/Kotlin | **OpenRewrite** (recipes) | type-aware recipes, dependency + API migrations at scale |
|
|
37
|
+
|
|
38
|
+
Default: **ast-grep** for a clean pattern→pattern swap in any language; **jscodeshift** when the JS/TS rewrite needs real logic; **ts-morph** when you must follow type references, not text.
|
|
39
|
+
|
|
40
|
+
2. **Characterize on 2–3 representative files first, then enumerate edge cases.** Open real call sites and write down what must and must NOT change. Hostile cases that break naive transforms:
|
|
41
|
+
- **Shadowing** — a local `const getUser = ...` that is *not* the imported symbol.
|
|
42
|
+
- **Re-exports / aliases** — `export { getUser as gu }`, `import { getUser as g }`.
|
|
43
|
+
- **Dynamic access** — `obj["getUser"]`, computed members, reflection — usually out of AST reach; list them as manual tail.
|
|
44
|
+
- **Strings & comments** — must be left alone unless explicitly targeted.
|
|
45
|
+
- **Formatting** — preserve it (recast/libcst/ts-morph do; a naive print does not).
|
|
46
|
+
- **Partial matches** — `getUserById` must not be caught by a `getUser` rule.
|
|
47
|
+
|
|
48
|
+
3. **Write the transform as code and test it on fixtures before touching the tree.** The codemod is software — assert before/after so a bad rule can't run silently. jscodeshift skeleton:
|
|
49
|
+
|
|
50
|
+
```js
|
|
51
|
+
// rename-getUser.js — jscodeshift transform
|
|
52
|
+
module.exports = function (file, api) {
|
|
53
|
+
const j = api.jscodeshift;
|
|
54
|
+
const root = j(file.source);
|
|
55
|
+
// only rename the IMPORTED binding, follow its local name (handles aliases)
|
|
56
|
+
root.find(j.ImportSpecifier, { imported: { name: 'getUser' } })
|
|
57
|
+
.forEach((p) => {
|
|
58
|
+
const local = p.node.local.name; // respects `as` alias
|
|
59
|
+
root.find(j.Identifier, { name: local })
|
|
60
|
+
.filter((id) => id.parent.node.type !== 'ImportSpecifier')
|
|
61
|
+
.forEach((id) => { id.node.name = 'fetchUser'; });
|
|
62
|
+
p.node.imported.name = 'fetchUser';
|
|
63
|
+
});
|
|
64
|
+
return root.toSource({ quote: 'single' });
|
|
65
|
+
};
|
|
66
|
+
```
|
|
67
|
+
```js
|
|
68
|
+
// rename-getUser.test.js — the codemod itself is under test
|
|
69
|
+
const { applyTransform } = require('jscodeshift/dist/testUtils');
|
|
70
|
+
const t = require('./rename-getUser');
|
|
71
|
+
test('renames imported symbol, not the shadow or the string', () => {
|
|
72
|
+
expect(applyTransform(t, {}, { source:
|
|
73
|
+
`import { getUser } from './api';\nconst x = getUser(1);\nlog("getUser");` }))
|
|
74
|
+
.toBe(
|
|
75
|
+
`import { fetchUser } from './api';\nconst x = fetchUser(1);\nlog("getUser");`);
|
|
76
|
+
});
|
|
77
|
+
```
|
|
78
|
+
ast-grep equivalent needs no test harness but still gets a fixture diff: `sg run -p 'getUser($A)' -r 'fetchUser($A)' --lang ts fixtures/ --dry-run`.
|
|
79
|
+
|
|
80
|
+
4. **Dry-run across the whole tree; review stats and sampled hunks; tune to zero false hits.** Never let the first run write. jscodeshift `--dry --print` (or `-d -p`), ast-grep `--dry-run`, Comby without `-i`, libcst via a `--no-write` flag. Inspect the **count** of changed files and read a random sample of hunks — if any touch a string, comment, or shadow, fix the rule and re-dry-run. Iterate until the only diff is the intended one.
|
|
81
|
+
|
|
82
|
+
5. **Apply, then immediately run the toolchain — the codemod's output is unverified until the build agrees.** Run formatter → linter → typecheck → tests in that order: `prettier --write` / `gofmt`, then `eslint --fix`, then `tsc --noEmit`, then the suite. A green typecheck is the strongest signal a JS/TS rename hit every real reference; a red one points straight at a missed or over-eager site.
|
|
83
|
+
|
|
84
|
+
6. **Handle the long tail manually and document it.** Dynamic access, generated code, vendored files, and cross-package boundaries the AST can't follow stay broken — `grep` the old name to find survivors, fix them by hand, and note in the commit what the codemod could not reach and why.
|
|
85
|
+
|
|
86
|
+
7. **Commit the transform script alongside its diff.** Check in the codemod file + its fixture test in the same commit as the generated changes, with the exact command in the message. The change becomes reproducible, reviewable as a rule (not N edits), and re-runnable when stragglers appear.
|
|
87
|
+
|
|
88
|
+
## Common Errors
|
|
89
|
+
|
|
90
|
+
- **`sed`/find-replace across a grammar.** Rewrites the symbol inside strings, comments, and shadowed locals. Use an AST tool that distinguishes node kinds.
|
|
91
|
+
- **Matching the name, not the binding.** A bare `Identifier` rename also hits an unrelated local `getUser`. Anchor to the import/declaration and follow its references (ts-morph `findReferences`, or trace the local name as in step 3).
|
|
92
|
+
- **Ignoring `as` aliases and re-exports.** `import { getUser as g }` renames nothing if you only look for `getUser` identifiers. Read `local` vs `imported`; rewrite both the export and its consumers.
|
|
93
|
+
- **Substring false positives.** A `getUser` text rule mangles `getUserById`/`getUsers`. AST identifier matching is exact; text rules need word boundaries and review.
|
|
94
|
+
- **Printing instead of patching the AST** (`root.toSource()` from a fresh print) reflows the whole file — huge noise diff. Use recast (jscodeshift default), libcst, or ts-morph to preserve untouched formatting.
|
|
95
|
+
- **No fixture test on the codemod.** A subtle rule bug silently corrupts hundreds of files. Assert before/after on representative inputs *before* the tree run.
|
|
96
|
+
- **Skipping the dry-run.** First run writes; you discover the over-match after it's everywhere. Always dry-run, read sampled hunks, then apply.
|
|
97
|
+
- **Trusting "0 errors" without a typecheck.** A rename can compile-pass yet miss dynamic call sites. Run `tsc`/tests after; `grep` the old name for survivors.
|
|
98
|
+
- **Letting the formatter mask a bad transform.** Running `prettier` first can hide a structural mistake behind reformatting. Diff the raw codemod output, *then* format.
|
|
99
|
+
- **One mega-transform doing five things.** Unreviewable and unrevertable. One codemod = one rule; chain separate scripts.
|
|
100
|
+
|
|
101
|
+
## Verify
|
|
102
|
+
|
|
103
|
+
1. **Fixture tests pass:** the codemod's own before/after assertions are green, including a shadow case, an alias/re-export case, and a string-that-must-not-change case.
|
|
104
|
+
2. **Dry-run is clean:** the dry-run diff contains only intended hunks — zero edits inside strings, comments, or shadowed locals (confirm by reading a random sample, not just the count).
|
|
105
|
+
3. **No stragglers:** `grep -rn '\bgetUser\b'` (old name, word-bounded) over the tree returns only the documented manual tail — nothing the codemod should have caught.
|
|
106
|
+
4. **Toolchain agrees:** formatter clean, linter clean, `tsc --noEmit` (or language equivalent) exits 0, full test suite passes on the transformed tree.
|
|
107
|
+
5. **Diff is minimal:** changed lines are the transform's effect only — no incidental reformatting of untouched code.
|
|
108
|
+
6. **Reproducible:** the codemod script + fixture test are committed with the diff and the exact run command; re-running the codemod on the result is a no-op.
|
|
109
|
+
|
|
110
|
+
Done = fixture tests + dry-run are clean, the post-apply toolchain (format/lint/typecheck/tests) is fully green, no undocumented stragglers remain, and the transform script ships in the same commit so the change re-runs deterministically.
|