omitnix 0.1.0__tar.gz
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.
- omitnix-0.1.0/.gitattributes +22 -0
- omitnix-0.1.0/.githooks/pre-commit +21 -0
- omitnix-0.1.0/.github/workflows/ci.yml +173 -0
- omitnix-0.1.0/.github/workflows/publish.yml +123 -0
- omitnix-0.1.0/.github/workflows/secrets-scan.yml +40 -0
- omitnix-0.1.0/.gitignore +94 -0
- omitnix-0.1.0/.omitnix/index.json +2062 -0
- omitnix-0.1.0/.omitnix.yaml +91 -0
- omitnix-0.1.0/.semgrep/README.md +71 -0
- omitnix-0.1.0/.semgrep/examples/orders_export.php +23 -0
- omitnix-0.1.0/.semgrep/examples/orders_list.php +11 -0
- omitnix-0.1.0/.semgrep/omitnix-contract.yaml +82 -0
- omitnix-0.1.0/AGENTS.md +26 -0
- omitnix-0.1.0/CHANGELOG.md +39 -0
- omitnix-0.1.0/CLAUDE.md +104 -0
- omitnix-0.1.0/LICENSE +21 -0
- omitnix-0.1.0/PKG-INFO +550 -0
- omitnix-0.1.0/README.md +489 -0
- omitnix-0.1.0/conftest.py +2 -0
- omitnix-0.1.0/lefthook.yml +43 -0
- omitnix-0.1.0/omitnix/__init__.py +10 -0
- omitnix-0.1.0/omitnix/__main__.py +8 -0
- omitnix-0.1.0/omitnix/adapters/__init__.py +9 -0
- omitnix-0.1.0/omitnix/adapters/_extract.py +439 -0
- omitnix-0.1.0/omitnix/adapters/_minimal.py +107 -0
- omitnix-0.1.0/omitnix/adapters/_sql.py +222 -0
- omitnix-0.1.0/omitnix/adapters/_treesitter.py +196 -0
- omitnix-0.1.0/omitnix/adapters/base.py +109 -0
- omitnix-0.1.0/omitnix/adapters/css.py +29 -0
- omitnix-0.1.0/omitnix/adapters/go.py +98 -0
- omitnix-0.1.0/omitnix/adapters/html.py +272 -0
- omitnix-0.1.0/omitnix/adapters/php.py +572 -0
- omitnix-0.1.0/omitnix/adapters/powershell.py +29 -0
- omitnix-0.1.0/omitnix/adapters/python.py +162 -0
- omitnix-0.1.0/omitnix/adapters/rust.py +27 -0
- omitnix-0.1.0/omitnix/adapters/shell.py +25 -0
- omitnix-0.1.0/omitnix/adapters/sql.py +143 -0
- omitnix-0.1.0/omitnix/adapters/tsjs.py +190 -0
- omitnix-0.1.0/omitnix/adapters/vue.py +31 -0
- omitnix-0.1.0/omitnix/analyze.py +398 -0
- omitnix-0.1.0/omitnix/cli.py +630 -0
- omitnix-0.1.0/omitnix/config.py +284 -0
- omitnix-0.1.0/omitnix/errors.py +42 -0
- omitnix-0.1.0/omitnix/gate.py +330 -0
- omitnix-0.1.0/omitnix/gitmeta.py +216 -0
- omitnix-0.1.0/omitnix/globs.py +99 -0
- omitnix-0.1.0/omitnix/model.py +428 -0
- omitnix-0.1.0/omitnix/queries/go.scm +35 -0
- omitnix-0.1.0/omitnix/queries/html.scm +42 -0
- omitnix-0.1.0/omitnix/queries/php.scm +55 -0
- omitnix-0.1.0/omitnix/queries/python.scm +38 -0
- omitnix-0.1.0/omitnix/queries/tsjs.scm +48 -0
- omitnix-0.1.0/omitnix/reasons.py +79 -0
- omitnix-0.1.0/omitnix/registry.py +147 -0
- omitnix-0.1.0/omitnix/render.py +68 -0
- omitnix-0.1.0/omitnix/scan.py +231 -0
- omitnix-0.1.0/omitnix/schema.py +42 -0
- omitnix-0.1.0/omitnix/workspace.py +847 -0
- omitnix-0.1.0/pyproject.toml +91 -0
- omitnix-0.1.0/scripts/check-claude-md.mjs +101 -0
- omitnix-0.1.0/scripts/install-hooks.ps1 +25 -0
- omitnix-0.1.0/scripts/install-hooks.sh +31 -0
- omitnix-0.1.0/scripts/secrets-scan.mjs +543 -0
- omitnix-0.1.0/tests/__init__.py +1 -0
- omitnix-0.1.0/tests/conftest.py +75 -0
- omitnix-0.1.0/tests/fixtures/adapters/flow.py +84 -0
- omitnix-0.1.0/tests/fixtures/adapters/note.py +34 -0
- omitnix-0.1.0/tests/fixtures/bad_adapters/overreaching.py +24 -0
- omitnix-0.1.0/tests/fixtures/go/broken.go +6 -0
- omitnix-0.1.0/tests/fixtures/go/export.go +16 -0
- omitnix-0.1.0/tests/fixtures/go/notes.go +8 -0
- omitnix-0.1.0/tests/fixtures/go/orders_list.go +20 -0
- omitnix-0.1.0/tests/fixtures/go/reindex.go +11 -0
- omitnix-0.1.0/tests/fixtures/html/about.htm +10 -0
- omitnix-0.1.0/tests/fixtures/html/interpolated.html +14 -0
- omitnix-0.1.0/tests/fixtures/html/interpolated_escaped.html +14 -0
- omitnix-0.1.0/tests/fixtures/html/notes.html +4 -0
- omitnix-0.1.0/tests/fixtures/html/orders.html +19 -0
- omitnix-0.1.0/tests/fixtures/html/stray_open_bracket.html +12 -0
- omitnix-0.1.0/tests/fixtures/html/templated.html +8 -0
- omitnix-0.1.0/tests/fixtures/minimal/banner.sh +9 -0
- omitnix-0.1.0/tests/fixtures/minimal/counter.rs +5 -0
- omitnix-0.1.0/tests/fixtures/minimal/deploy.ps1 +9 -0
- omitnix-0.1.0/tests/fixtures/minimal/deploy.sh +6 -0
- omitnix-0.1.0/tests/fixtures/minimal/panel.vue +12 -0
- omitnix-0.1.0/tests/fixtures/minimal/styles.css +6 -0
- omitnix-0.1.0/tests/fixtures/new/health_check.flow +1 -0
- omitnix-0.1.0/tests/fixtures/new/orders_list.flow +4 -0
- omitnix-0.1.0/tests/fixtures/new/orders_purge.flow +3 -0
- omitnix-0.1.0/tests/fixtures/new/reindex.flow +6 -0
- omitnix-0.1.0/tests/fixtures/new/release.note +1 -0
- omitnix-0.1.0/tests/fixtures/new/theme.unmapped +3 -0
- omitnix-0.1.0/tests/fixtures/new/undocumented.flow +3 -0
- omitnix-0.1.0/tests/fixtures/new/unreadable.flow +2 -0
- omitnix-0.1.0/tests/fixtures/php/audit.php +10 -0
- omitnix-0.1.0/tests/fixtures/php/broken.php +9 -0
- omitnix-0.1.0/tests/fixtures/php/common/queries.php +18 -0
- omitnix-0.1.0/tests/fixtures/php/common/reports.php +14 -0
- omitnix-0.1.0/tests/fixtures/php/declared.php +17 -0
- omitnix-0.1.0/tests/fixtures/php/export.php +9 -0
- omitnix-0.1.0/tests/fixtures/php/legacy_report.php +12 -0
- omitnix-0.1.0/tests/fixtures/php/notes.php +4 -0
- omitnix-0.1.0/tests/fixtures/php/orders_list.php +13 -0
- omitnix-0.1.0/tests/fixtures/php/reindex.php +6 -0
- omitnix-0.1.0/tests/fixtures/php/router.php +8 -0
- omitnix-0.1.0/tests/fixtures/php/schema.json +8 -0
- omitnix-0.1.0/tests/fixtures/php/summary.php +8 -0
- omitnix-0.1.0/tests/fixtures/python/audit.py +11 -0
- omitnix-0.1.0/tests/fixtures/python/broken.py +5 -0
- omitnix-0.1.0/tests/fixtures/python/client.pyi +8 -0
- omitnix-0.1.0/tests/fixtures/python/export.py +7 -0
- omitnix-0.1.0/tests/fixtures/python/legacy_report.py +12 -0
- omitnix-0.1.0/tests/fixtures/python/notes.py +5 -0
- omitnix-0.1.0/tests/fixtures/python/orders_list.py +19 -0
- omitnix-0.1.0/tests/fixtures/python/reindex.py +8 -0
- omitnix-0.1.0/tests/fixtures/rival_adapters/rival_flow.py +22 -0
- omitnix-0.1.0/tests/fixtures/sql/migrate_audit.sql +10 -0
- omitnix-0.1.0/tests/fixtures/sql/notes.sql +2 -0
- omitnix-0.1.0/tests/fixtures/sql/report.sql +6 -0
- omitnix-0.1.0/tests/fixtures/sql/salvage.sql +8 -0
- omitnix-0.1.0/tests/fixtures/sql/schema.sql +17 -0
- omitnix-0.1.0/tests/fixtures/sql/vendor.sql +7 -0
- omitnix-0.1.0/tests/fixtures/tsjs/audit.js +16 -0
- omitnix-0.1.0/tests/fixtures/tsjs/broken.js +4 -0
- omitnix-0.1.0/tests/fixtures/tsjs/client.cjs +7 -0
- omitnix-0.1.0/tests/fixtures/tsjs/orders_list.ts +15 -0
- omitnix-0.1.0/tests/fixtures/tsjs/panel.tsx +8 -0
- omitnix-0.1.0/tests/fixtures/tsjs/reindex.mjs +9 -0
- omitnix-0.1.0/tests/test_adapter_go.py +216 -0
- omitnix-0.1.0/tests/test_adapter_html.py +266 -0
- omitnix-0.1.0/tests/test_adapter_minimal.py +222 -0
- omitnix-0.1.0/tests/test_adapter_python.py +285 -0
- omitnix-0.1.0/tests/test_adapter_sql.py +167 -0
- omitnix-0.1.0/tests/test_adapter_tsjs.py +231 -0
- omitnix-0.1.0/tests/test_analyze.py +434 -0
- omitnix-0.1.0/tests/test_cli.py +418 -0
- omitnix-0.1.0/tests/test_config.py +63 -0
- omitnix-0.1.0/tests/test_determinism.py +74 -0
- omitnix-0.1.0/tests/test_gate.py +701 -0
- omitnix-0.1.0/tests/test_globs.py +53 -0
- omitnix-0.1.0/tests/test_php_adapter.py +459 -0
- omitnix-0.1.0/tests/test_reasons.py +89 -0
- omitnix-0.1.0/tests/test_registry.py +96 -0
- omitnix-0.1.0/tests/test_render.py +259 -0
- omitnix-0.1.0/tests/test_workspace.py +709 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Line endings.
|
|
2
|
+
#
|
|
3
|
+
# Without this file, a clone on a machine with core.autocrlf=true gets CRLF in the
|
|
4
|
+
# working tree for every text file. Two things here break when that happens, and both
|
|
5
|
+
# break quietly enough to waste an afternoon:
|
|
6
|
+
#
|
|
7
|
+
# * .githooks/pre-commit is run by sh. A trailing CR turns the last argument of every
|
|
8
|
+
# line into something ending in \r, and the error names the wrong thing entirely
|
|
9
|
+
# ("$'\r': command not found").
|
|
10
|
+
# * .omitnix/ holds documents this tool writes with LF on every platform, on purpose,
|
|
11
|
+
# so that the machine which generated them does not show up as a diff. Letting the
|
|
12
|
+
# checkout put CRLF back means the working tree disagrees with what the tool emits.
|
|
13
|
+
#
|
|
14
|
+
# Fixtures are analyzer input rather than prose: their bytes are the test, so they are
|
|
15
|
+
# pinned too.
|
|
16
|
+
|
|
17
|
+
* text=auto
|
|
18
|
+
|
|
19
|
+
*.sh text eol=lf
|
|
20
|
+
.githooks/* text eol=lf
|
|
21
|
+
.omitnix/* text eol=lf
|
|
22
|
+
tests/fixtures/** text eol=lf
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env sh
|
|
2
|
+
# secrets-scan layer 2 (per-commit) — non-pnpm path via core.hooksPath = .githooks
|
|
3
|
+
# 設計詳細: docs/local/secrets-scan-design/ (gitignored)
|
|
4
|
+
# Activate with: bash scripts/install-hooks.sh or pwsh scripts/install-hooks.ps1
|
|
5
|
+
#
|
|
6
|
+
# 検査を足すときは必ず `|| exit 1` を付ける。付けずに 2 本目を並べると hook の
|
|
7
|
+
# 終了コードが「最後のコマンドの結果」になり、前段の BLOCKED が握り潰される。
|
|
8
|
+
node scripts/secrets-scan.mjs --staged --block || exit 1
|
|
9
|
+
node scripts/check-claude-md.mjs || exit 1
|
|
10
|
+
|
|
11
|
+
# omitnix の新規ファイル gate。lefthook.yml の pre-commit を実行する。
|
|
12
|
+
# lefthook install は使わない(このファイルを上書きして上の 2 本を消すため)。
|
|
13
|
+
# lefthook が無いときは黙って飛ばさず、ここで止める。検査を静かに省略しないのが
|
|
14
|
+
# このリポジトリの主題そのもの。
|
|
15
|
+
if command -v lefthook >/dev/null 2>&1; then
|
|
16
|
+
lefthook run pre-commit || exit 1
|
|
17
|
+
else
|
|
18
|
+
echo "BLOCKED: lefthook が見つかりません。scoop install lefthook(または winget install evilmartians.lefthook)で入れてください。" >&2
|
|
19
|
+
echo " この 1 本を飛ばすと、新規ファイルの gate が動かないままコミットされます。" >&2
|
|
20
|
+
exit 1
|
|
21
|
+
fi
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
name: ci
|
|
2
|
+
|
|
3
|
+
# Lint, tests, and the tool run against its own repository.
|
|
4
|
+
#
|
|
5
|
+
# The OS matrix is the point of this file, not a formality. The tool is developed on
|
|
6
|
+
# Windows only, so ubuntu-latest and macos-latest here are the first and only place its
|
|
7
|
+
# behaviour on those platforms is observed at all. `-latest` is deliberate: the question
|
|
8
|
+
# is whether the current runners work, not whether some pinned production image does --
|
|
9
|
+
# nothing here depends on a system library version.
|
|
10
|
+
#
|
|
11
|
+
# No secrets are used, and none should be added. The tool never connects to a database:
|
|
12
|
+
# schema information, where it is used at all, comes from a JSON snapshot committed by
|
|
13
|
+
# the repository being scanned.
|
|
14
|
+
|
|
15
|
+
on:
|
|
16
|
+
pull_request:
|
|
17
|
+
push:
|
|
18
|
+
branches:
|
|
19
|
+
- main
|
|
20
|
+
- develop
|
|
21
|
+
|
|
22
|
+
permissions:
|
|
23
|
+
contents: read
|
|
24
|
+
|
|
25
|
+
concurrency:
|
|
26
|
+
group: ci-${{ github.workflow }}-${{ github.ref }}
|
|
27
|
+
cancel-in-progress: true
|
|
28
|
+
|
|
29
|
+
jobs:
|
|
30
|
+
lint:
|
|
31
|
+
name: lint
|
|
32
|
+
runs-on: ubuntu-latest
|
|
33
|
+
steps:
|
|
34
|
+
- name: Checkout
|
|
35
|
+
uses: actions/checkout@v4
|
|
36
|
+
|
|
37
|
+
- name: Setup Python
|
|
38
|
+
uses: actions/setup-python@v5
|
|
39
|
+
with:
|
|
40
|
+
python-version: '3.14'
|
|
41
|
+
|
|
42
|
+
# Pinned to the version used locally on 2026-09-08. ruff is not a declared
|
|
43
|
+
# dependency of the project, so without a pin a new release could fail the build
|
|
44
|
+
# on a rule nobody chose to adopt.
|
|
45
|
+
- name: Install ruff
|
|
46
|
+
run: python -m pip install ruff==0.16.2
|
|
47
|
+
|
|
48
|
+
- name: ruff check
|
|
49
|
+
run: python -m ruff check .
|
|
50
|
+
|
|
51
|
+
test:
|
|
52
|
+
name: test ${{ matrix.os }} py${{ matrix.python-version }}
|
|
53
|
+
runs-on: ${{ matrix.os }}
|
|
54
|
+
strategy:
|
|
55
|
+
fail-fast: false
|
|
56
|
+
matrix:
|
|
57
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
58
|
+
# The declared floor and the version actually developed against.
|
|
59
|
+
python-version: ['3.11', '3.14']
|
|
60
|
+
steps:
|
|
61
|
+
- name: Checkout
|
|
62
|
+
uses: actions/checkout@v4
|
|
63
|
+
|
|
64
|
+
- name: Setup Python
|
|
65
|
+
uses: actions/setup-python@v5
|
|
66
|
+
with:
|
|
67
|
+
python-version: ${{ matrix.python-version }}
|
|
68
|
+
|
|
69
|
+
# --only-binary names the two compiled dependencies, so a missing wheel fails here
|
|
70
|
+
# instead of being papered over by a source build on whichever runners happen to
|
|
71
|
+
# have a compiler. That is the thing being tested: `pip install omitnix[php]` has
|
|
72
|
+
# to work on a machine with no toolchain. The local project itself is not in the
|
|
73
|
+
# list and still builds normally.
|
|
74
|
+
- name: Install with every parser, wheels only for the compiled ones
|
|
75
|
+
run: |
|
|
76
|
+
python -m pip install --upgrade pip
|
|
77
|
+
python -m pip install --only-binary tree-sitter,tree-sitter-php,tree-sitter-python,tree-sitter-go,tree-sitter-typescript,tree-sitter-javascript,tree-sitter-html -e ".[dev]"
|
|
78
|
+
|
|
79
|
+
# Recorded so the log says which parser versions a green run actually covered.
|
|
80
|
+
- name: Report resolved versions
|
|
81
|
+
run: python -m pip list
|
|
82
|
+
|
|
83
|
+
- name: pytest
|
|
84
|
+
run: python -m pytest -q
|
|
85
|
+
|
|
86
|
+
dogfood:
|
|
87
|
+
name: dogfood ${{ matrix.os }}
|
|
88
|
+
runs-on: ${{ matrix.os }}
|
|
89
|
+
strategy:
|
|
90
|
+
fail-fast: false
|
|
91
|
+
matrix:
|
|
92
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
93
|
+
steps:
|
|
94
|
+
- name: Checkout
|
|
95
|
+
uses: actions/checkout@v4
|
|
96
|
+
|
|
97
|
+
- name: Setup Python
|
|
98
|
+
uses: actions/setup-python@v5
|
|
99
|
+
with:
|
|
100
|
+
python-version: '3.14'
|
|
101
|
+
|
|
102
|
+
# Every adapter, because this job asks whether the committed inventory matches a
|
|
103
|
+
# fresh run: with a grammar missing, the files it covers come back as `unknown`
|
|
104
|
+
# and the comparison fails for a reason that has nothing to do with the inventory.
|
|
105
|
+
- name: Install with every parser
|
|
106
|
+
run: |
|
|
107
|
+
python -m pip install --upgrade pip
|
|
108
|
+
python -m pip install -e ".[all]"
|
|
109
|
+
|
|
110
|
+
# --check writes nothing and compares the committed documents in .omitnix/ against
|
|
111
|
+
# a fresh run, so this one step covers both questions: was everything discovered
|
|
112
|
+
# analyzed (exit 1 if not), and is the committed inventory still current (exit 3 if
|
|
113
|
+
# not). Run on all three platforms because discovery is where the path handling
|
|
114
|
+
# lives -- the walk, the glob translation, and the exclusions in .omitnix.yaml are
|
|
115
|
+
# the parts most likely to behave differently off Windows.
|
|
116
|
+
#
|
|
117
|
+
# A failure here means one of: a new file type nobody gave an adapter, or someone
|
|
118
|
+
# changed the code without regenerating. Both are fixed by running `omitnix` and
|
|
119
|
+
# committing the result.
|
|
120
|
+
- name: Check the committed inventory against a fresh run
|
|
121
|
+
run: python -m omitnix --check
|
|
122
|
+
|
|
123
|
+
gate:
|
|
124
|
+
name: gate
|
|
125
|
+
runs-on: ubuntu-latest
|
|
126
|
+
steps:
|
|
127
|
+
# The gate needs the base commit to exist locally, and a shallow clone does not
|
|
128
|
+
# have it. It refuses rather than reporting that nothing was added, so getting
|
|
129
|
+
# this wrong is a red run and not a silent pass -- but a red run for the wrong
|
|
130
|
+
# reason is still a waste of everyone's morning.
|
|
131
|
+
- name: Checkout
|
|
132
|
+
uses: actions/checkout@v4
|
|
133
|
+
with:
|
|
134
|
+
fetch-depth: 0
|
|
135
|
+
|
|
136
|
+
- name: Setup Python
|
|
137
|
+
uses: actions/setup-python@v5
|
|
138
|
+
with:
|
|
139
|
+
python-version: '3.14'
|
|
140
|
+
|
|
141
|
+
- name: Install with every parser
|
|
142
|
+
run: |
|
|
143
|
+
python -m pip install --upgrade pip
|
|
144
|
+
python -m pip install -e ".[all]"
|
|
145
|
+
|
|
146
|
+
# Which commit the branch is measured against. On a pull request it is the base
|
|
147
|
+
# branch; on a push it is where the branch was before the push.
|
|
148
|
+
#
|
|
149
|
+
# `github.event.before` is all zeros for the first push of a new branch, and a
|
|
150
|
+
# merge-base against that does not exist. The default branch is used instead: on a
|
|
151
|
+
# brand new branch that is the honest baseline anyway, and asking for slightly too
|
|
152
|
+
# much is the safe direction for a gate.
|
|
153
|
+
- name: Decide the baseline
|
|
154
|
+
id: baseline
|
|
155
|
+
env:
|
|
156
|
+
BEFORE: ${{ github.event.before }}
|
|
157
|
+
BASE_REF: ${{ github.base_ref }}
|
|
158
|
+
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
|
|
159
|
+
run: |
|
|
160
|
+
if [ -n "$BASE_REF" ]; then
|
|
161
|
+
echo "ref=origin/$BASE_REF" >> "$GITHUB_OUTPUT"
|
|
162
|
+
elif [ -n "$BEFORE" ] && [ "$BEFORE" != "0000000000000000000000000000000000000000" ]; then
|
|
163
|
+
echo "ref=$BEFORE" >> "$GITHUB_OUTPUT"
|
|
164
|
+
else
|
|
165
|
+
echo "ref=origin/$DEFAULT_BRANCH" >> "$GITHUB_OUTPUT"
|
|
166
|
+
fi
|
|
167
|
+
|
|
168
|
+
# The reason this job exists. The pre-commit hook asks the working tree what is
|
|
169
|
+
# new, which only has an answer on the machine that is about to make the commit --
|
|
170
|
+
# so the hook's coverage is however many people happened to install it. This asks
|
|
171
|
+
# about a range instead, which holds for work anyone committed.
|
|
172
|
+
- name: Gate the files this branch added
|
|
173
|
+
run: python -m omitnix --gate --since "${{ steps.baseline.outputs.ref }}"
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
name: publish
|
|
2
|
+
|
|
3
|
+
# Tag-driven publication to PyPI through Trusted Publishing (OIDC).
|
|
4
|
+
#
|
|
5
|
+
# There is no API token anywhere in this file and none should be added. PyPI is told,
|
|
6
|
+
# once, which repository and which workflow file may publish this project; the token the
|
|
7
|
+
# upload uses is minted for that one run and expires with it. Nothing here can be leaked
|
|
8
|
+
# from a log or a fork, because nothing here is a secret.
|
|
9
|
+
#
|
|
10
|
+
# To release: set the version in pyproject.toml and omitnix/__init__.py, push the commit,
|
|
11
|
+
# then push the tag `vX.Y.Z`. The version guard below refuses the run if the three
|
|
12
|
+
# disagree -- a published version number can never be reused, so a mismatched tag has to
|
|
13
|
+
# fail before the upload, not after.
|
|
14
|
+
#
|
|
15
|
+
# The test job is not a formality either. `ci.yml` runs on pushes to main and on pull
|
|
16
|
+
# requests; a tag push triggers neither, so without this the only thing standing between
|
|
17
|
+
# an untested tree and PyPI would be remembering to look.
|
|
18
|
+
|
|
19
|
+
on:
|
|
20
|
+
push:
|
|
21
|
+
tags:
|
|
22
|
+
- "v*"
|
|
23
|
+
workflow_dispatch: {}
|
|
24
|
+
|
|
25
|
+
permissions:
|
|
26
|
+
contents: read
|
|
27
|
+
|
|
28
|
+
jobs:
|
|
29
|
+
verify:
|
|
30
|
+
name: verify the tag and the tree
|
|
31
|
+
runs-on: ubuntu-latest
|
|
32
|
+
steps:
|
|
33
|
+
- name: Checkout
|
|
34
|
+
uses: actions/checkout@v4
|
|
35
|
+
|
|
36
|
+
- name: Setup Python
|
|
37
|
+
uses: actions/setup-python@v5
|
|
38
|
+
with:
|
|
39
|
+
python-version: '3.14'
|
|
40
|
+
|
|
41
|
+
# The tag is the only one of the three that cannot be corrected after the fact.
|
|
42
|
+
- name: Refuse a tag that disagrees with the package version
|
|
43
|
+
if: startsWith(github.ref, 'refs/tags/')
|
|
44
|
+
run: |
|
|
45
|
+
tag="${GITHUB_REF_NAME#v}"
|
|
46
|
+
pyproject="$(python -c "import tomllib,pathlib;print(tomllib.loads(pathlib.Path('pyproject.toml').read_text())['project']['version'])")"
|
|
47
|
+
package="$(python -c "import pathlib,re;print(re.search(r'__version__ = \"([^\"]+)\"', pathlib.Path('omitnix/__init__.py').read_text()).group(1))")"
|
|
48
|
+
echo "tag=$tag pyproject=$pyproject package=$package"
|
|
49
|
+
if [ "$tag" != "$pyproject" ] || [ "$tag" != "$package" ]; then
|
|
50
|
+
echo "::error::the tag, pyproject.toml and omitnix/__init__.py must name the same version"
|
|
51
|
+
exit 1
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
# Every parser, so that the adapters are exercised rather than reporting unknown.
|
|
55
|
+
- name: Install the package with every extra
|
|
56
|
+
run: |
|
|
57
|
+
python -m pip install --upgrade pip
|
|
58
|
+
python -m pip install -e ".[dev]"
|
|
59
|
+
|
|
60
|
+
- name: Tests
|
|
61
|
+
run: python -m pytest -q
|
|
62
|
+
|
|
63
|
+
- name: The tool against its own repository
|
|
64
|
+
run: python -m omitnix --check
|
|
65
|
+
|
|
66
|
+
build:
|
|
67
|
+
name: build sdist and wheel
|
|
68
|
+
needs: verify
|
|
69
|
+
runs-on: ubuntu-latest
|
|
70
|
+
steps:
|
|
71
|
+
- name: Checkout
|
|
72
|
+
uses: actions/checkout@v4
|
|
73
|
+
|
|
74
|
+
- name: Setup Python
|
|
75
|
+
uses: actions/setup-python@v5
|
|
76
|
+
with:
|
|
77
|
+
python-version: '3.14'
|
|
78
|
+
|
|
79
|
+
- name: Install build tooling
|
|
80
|
+
run: python -m pip install --upgrade build
|
|
81
|
+
|
|
82
|
+
- name: Build distributions
|
|
83
|
+
run: python -m build
|
|
84
|
+
|
|
85
|
+
# hatchling selects files by what git tracks, so an untracked query file would be
|
|
86
|
+
# missing from the wheel while the build stayed green. The adapter that needs it
|
|
87
|
+
# then raises AdapterContractError on the user's machine and nowhere else.
|
|
88
|
+
- name: Refuse a wheel that is missing a query file
|
|
89
|
+
run: |
|
|
90
|
+
python - <<'PY'
|
|
91
|
+
import pathlib, zipfile, sys
|
|
92
|
+
|
|
93
|
+
wheel = next(pathlib.Path("dist").glob("*.whl"))
|
|
94
|
+
shipped = {n for n in zipfile.ZipFile(wheel).namelist() if n.endswith(".scm")}
|
|
95
|
+
expected = {f"omitnix/queries/{p.name}" for p in pathlib.Path("omitnix/queries").glob("*.scm")}
|
|
96
|
+
missing = sorted(expected - shipped)
|
|
97
|
+
if missing:
|
|
98
|
+
sys.exit(f"{wheel.name} is missing: {', '.join(missing)}")
|
|
99
|
+
print(f"{wheel.name} ships {len(shipped)} query files")
|
|
100
|
+
PY
|
|
101
|
+
|
|
102
|
+
- name: Upload artifacts
|
|
103
|
+
uses: actions/upload-artifact@v4
|
|
104
|
+
with:
|
|
105
|
+
name: dist
|
|
106
|
+
path: dist/
|
|
107
|
+
|
|
108
|
+
publish:
|
|
109
|
+
name: publish to PyPI
|
|
110
|
+
needs: build
|
|
111
|
+
runs-on: ubuntu-latest
|
|
112
|
+
environment: pypi
|
|
113
|
+
permissions:
|
|
114
|
+
id-token: write # the OIDC token Trusted Publishing exchanges for an upload
|
|
115
|
+
steps:
|
|
116
|
+
- name: Download artifacts
|
|
117
|
+
uses: actions/download-artifact@v4
|
|
118
|
+
with:
|
|
119
|
+
name: dist
|
|
120
|
+
path: dist/
|
|
121
|
+
|
|
122
|
+
- name: Publish via Trusted Publishing
|
|
123
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
name: secrets-scan
|
|
2
|
+
|
|
3
|
+
# Layer 3 of the kb-driven secrets-scan defense (per docs/local/secrets-scan-design/).
|
|
4
|
+
# Re-runs the same scripts/secrets-scan.mjs as the local husky pre-commit hook (layer 2),
|
|
5
|
+
# acting as the server-side backstop if the hook was bypassed or absent.
|
|
6
|
+
#
|
|
7
|
+
# Note: the CI runner does NOT have access to D:/dev/kb, so kb-derived watchlist
|
|
8
|
+
# matches will be skipped. Only the structural regex (Windows/POSIX absolute paths,
|
|
9
|
+
# RFC1918 private IPs) runs on this side. Layer 2 catches kb-derived leaks locally;
|
|
10
|
+
# layer 4 (release skill) runs against the full kb on the release machine.
|
|
11
|
+
|
|
12
|
+
on:
|
|
13
|
+
push:
|
|
14
|
+
branches:
|
|
15
|
+
- main
|
|
16
|
+
- develop
|
|
17
|
+
- 'hotfix/**'
|
|
18
|
+
- 'release/**'
|
|
19
|
+
pull_request:
|
|
20
|
+
branches:
|
|
21
|
+
- main
|
|
22
|
+
- develop
|
|
23
|
+
|
|
24
|
+
jobs:
|
|
25
|
+
scan:
|
|
26
|
+
name: scan tracked files
|
|
27
|
+
runs-on: ubuntu-latest
|
|
28
|
+
steps:
|
|
29
|
+
- name: Checkout
|
|
30
|
+
uses: actions/checkout@v4
|
|
31
|
+
with:
|
|
32
|
+
fetch-depth: 0
|
|
33
|
+
|
|
34
|
+
- name: Setup Node
|
|
35
|
+
uses: actions/setup-node@v4
|
|
36
|
+
with:
|
|
37
|
+
node-version: '20'
|
|
38
|
+
|
|
39
|
+
- name: Run secrets-scan (structural only on CI; kb not available)
|
|
40
|
+
run: node scripts/secrets-scan.mjs --all-tracked --block
|
omitnix-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# === Python ===
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.egg-info/
|
|
6
|
+
.eggs/
|
|
7
|
+
*.egg
|
|
8
|
+
build/
|
|
9
|
+
dist/
|
|
10
|
+
.venv/
|
|
11
|
+
venv/
|
|
12
|
+
env/
|
|
13
|
+
|
|
14
|
+
# === Python テスト・型・lint キャッシュ ===
|
|
15
|
+
.pytest_cache/
|
|
16
|
+
.coverage
|
|
17
|
+
.coverage.*
|
|
18
|
+
htmlcov/
|
|
19
|
+
.tox/
|
|
20
|
+
.mypy_cache/
|
|
21
|
+
.ruff_cache/
|
|
22
|
+
# === OS / エディタ ===
|
|
23
|
+
.DS_Store
|
|
24
|
+
Thumbs.db
|
|
25
|
+
desktop.ini
|
|
26
|
+
.idea/
|
|
27
|
+
.vscode/
|
|
28
|
+
*.swp
|
|
29
|
+
*.swo
|
|
30
|
+
# === ログ・一時・スクラッチ ===
|
|
31
|
+
*.log
|
|
32
|
+
*.jsonl
|
|
33
|
+
*.tmp
|
|
34
|
+
*.bak
|
|
35
|
+
*.orig
|
|
36
|
+
*.rej
|
|
37
|
+
# === AI ツールのローカル状態(トークンを含む可能性あり) ===
|
|
38
|
+
.claude/
|
|
39
|
+
# Cursor Agent CLI にはグローバル指示の口が無いため、共通ルールへのポインタを
|
|
40
|
+
# .cursor/rules に置く運用。ローカル環境固有の内容を含むので追跡しない。
|
|
41
|
+
.cursor/
|
|
42
|
+
.codex-tmp/
|
|
43
|
+
# many-ai-cli が opencode セッション中だけ cwd に書く permission 設定と排他ロック。
|
|
44
|
+
# セッションが kill されると置き去りになる(orchestration 子が書くのは "*": "allow")。
|
|
45
|
+
# tracked file には gitignore が効かないので、opencode 設定を意図して commit する
|
|
46
|
+
# リポジトリがあってもこの行は影響しない。
|
|
47
|
+
opencode.json*
|
|
48
|
+
# === ツール生成キャッシュ(アカウント ID 等の識別子を含み得る・追跡しない) ===
|
|
49
|
+
.wrangler/
|
|
50
|
+
.vercel/
|
|
51
|
+
.netlify/
|
|
52
|
+
.firebase/
|
|
53
|
+
.turbo/
|
|
54
|
+
.parcel-cache/
|
|
55
|
+
.terraform/
|
|
56
|
+
.serverless/
|
|
57
|
+
**/supabase/.temp/
|
|
58
|
+
# docsweep のローカル state / 旧世代 backup(v0.4+ は no-op だが旧版が生成し得るため常に ignore)
|
|
59
|
+
.docsweep/
|
|
60
|
+
# === ローカル/プライベート追記(fresh public clone から除外) ===
|
|
61
|
+
.env
|
|
62
|
+
.env.*
|
|
63
|
+
!.env.example
|
|
64
|
+
*.local
|
|
65
|
+
*.local.*
|
|
66
|
+
*.local.md
|
|
67
|
+
*.local.json
|
|
68
|
+
# docs/local/ は作業ノート(plan / bugfix / pending / recap)の置き場。
|
|
69
|
+
# public リポでは追跡しない。private リポでのみ tracked にしてよい(後日 grep するため)。
|
|
70
|
+
# 判断軸は「秘匿情報を書くか」ではなく「リポが公開されているか」。
|
|
71
|
+
docs/local/
|
|
72
|
+
scripts/local/
|
|
73
|
+
# === 認証情報・secrets・鍵(public へ絶対に出さない) ===
|
|
74
|
+
*.pem
|
|
75
|
+
*.key
|
|
76
|
+
*.p12
|
|
77
|
+
*.pfx
|
|
78
|
+
*.ppk
|
|
79
|
+
id_rsa
|
|
80
|
+
id_dsa
|
|
81
|
+
id_ecdsa
|
|
82
|
+
id_ed25519
|
|
83
|
+
secrets.*
|
|
84
|
+
*.secret.*
|
|
85
|
+
*credential*
|
|
86
|
+
.netrc
|
|
87
|
+
.npmrc
|
|
88
|
+
.pypirc
|
|
89
|
+
|
|
90
|
+
# === secrets-scan exception ===
|
|
91
|
+
!scripts/secrets-scan.mjs
|
|
92
|
+
# === obsidian-link: managed ===
|
|
93
|
+
/docs/obsidian/
|
|
94
|
+
# === /obsidian-link: managed ===
|