silica-core 0.7.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.
Files changed (170) hide show
  1. silica_core-0.7.0/.agents/plugins/marketplace.json +20 -0
  2. silica_core-0.7.0/.claude-plugin/marketplace.json +14 -0
  3. silica_core-0.7.0/.claude-plugin/plugin.json +17 -0
  4. silica_core-0.7.0/.codex-plugin/plugin.json +22 -0
  5. silica_core-0.7.0/.dockerignore +15 -0
  6. silica_core-0.7.0/.env.example +77 -0
  7. silica_core-0.7.0/.github/FUNDING.yml +4 -0
  8. silica_core-0.7.0/.github/ISSUE_TEMPLATE/bug_report.yml +26 -0
  9. silica_core-0.7.0/.github/ISSUE_TEMPLATE/config.yml +15 -0
  10. silica_core-0.7.0/.github/ISSUE_TEMPLATE/feature_request.yml +18 -0
  11. silica_core-0.7.0/.github/PULL_REQUEST_TEMPLATE.md +13 -0
  12. silica_core-0.7.0/.github/dependabot.yml +31 -0
  13. silica_core-0.7.0/.github/workflows/ci.yml +83 -0
  14. silica_core-0.7.0/.github/workflows/release-shim.yml +67 -0
  15. silica_core-0.7.0/.github/workflows/release.yml +87 -0
  16. silica_core-0.7.0/.gitignore +126 -0
  17. silica_core-0.7.0/CODE_OF_CONDUCT.md +133 -0
  18. silica_core-0.7.0/CONTRIBUTING.md +48 -0
  19. silica_core-0.7.0/Dockerfile +35 -0
  20. silica_core-0.7.0/LICENSE +661 -0
  21. silica_core-0.7.0/LICENSE-COMMERCIAL.md +62 -0
  22. silica_core-0.7.0/PKG-INFO +220 -0
  23. silica_core-0.7.0/README.md +173 -0
  24. silica_core-0.7.0/SECURITY.md +34 -0
  25. silica_core-0.7.0/TOOLS.md +208 -0
  26. silica_core-0.7.0/assets/banner-light.svg +13 -0
  27. silica_core-0.7.0/assets/banner.svg +13 -0
  28. silica_core-0.7.0/assets/build_banners.py +231 -0
  29. silica_core-0.7.0/assets/sili_mascot.png +0 -0
  30. silica_core-0.7.0/assets/silica-mark-favicon.svg +1 -0
  31. silica_core-0.7.0/assets/silica-mark.svg +1 -0
  32. silica_core-0.7.0/cliff.toml +46 -0
  33. silica_core-0.7.0/mcp.codex.json +8 -0
  34. silica_core-0.7.0/mcp.json +16 -0
  35. silica_core-0.7.0/packaging/silica-agent/README.md +13 -0
  36. silica_core-0.7.0/packaging/silica-agent/pyproject.toml +53 -0
  37. silica_core-0.7.0/packaging/silica-harness/README.md +13 -0
  38. silica_core-0.7.0/packaging/silica-harness/pyproject.toml +52 -0
  39. silica_core-0.7.0/pyproject.toml +138 -0
  40. silica_core-0.7.0/setup.cfg +4 -0
  41. silica_core-0.7.0/silica/.env.example +77 -0
  42. silica_core-0.7.0/silica/__init__.py +39 -0
  43. silica_core-0.7.0/silica/_version.py +24 -0
  44. silica_core-0.7.0/silica/cli.py +190 -0
  45. silica_core-0.7.0/silica/config.py +113 -0
  46. silica_core-0.7.0/silica/core.py +728 -0
  47. silica_core-0.7.0/silica/driver/__init__.py +127 -0
  48. silica_core-0.7.0/silica/driver/base.py +347 -0
  49. silica_core-0.7.0/silica/driver/fs_backend.py +1198 -0
  50. silica_core-0.7.0/silica/driver/ws_backend.py +582 -0
  51. silica_core-0.7.0/silica/embeddings.py +98 -0
  52. silica_core-0.7.0/silica/entry.py +10 -0
  53. silica_core-0.7.0/silica/kernel/__init__.py +9 -0
  54. silica_core-0.7.0/silica/kernel/code/__init__.py +4 -0
  55. silica_core-0.7.0/silica/kernel/code/codeast/__init__.py +31 -0
  56. silica_core-0.7.0/silica/kernel/code/codeast/base.py +230 -0
  57. silica_core-0.7.0/silica/kernel/code/codeast/c.py +215 -0
  58. silica_core-0.7.0/silica/kernel/code/codeast/java.py +190 -0
  59. silica_core-0.7.0/silica/kernel/code/codeast/python.py +317 -0
  60. silica_core-0.7.0/silica/kernel/code/codeast/ts.py +262 -0
  61. silica_core-0.7.0/silica/kernel/code/codegraph.py +516 -0
  62. silica_core-0.7.0/silica/kernel/code/codepack.py +510 -0
  63. silica_core-0.7.0/silica/kernel/code/gitstate.py +310 -0
  64. silica_core-0.7.0/silica/kernel/code/ipynb.py +71 -0
  65. silica_core-0.7.0/silica/kernel/link/__init__.py +4 -0
  66. silica_core-0.7.0/silica/kernel/link/ast.py +400 -0
  67. silica_core-0.7.0/silica/kernel/link/ofm.py +159 -0
  68. silica_core-0.7.0/silica/kernel/recall/__init__.py +4 -0
  69. silica_core-0.7.0/silica/kernel/recall/lexical.py +326 -0
  70. silica_core-0.7.0/silica/kernel/recall/paths.py +865 -0
  71. silica_core-0.7.0/silica/kernel/recall/rerank.py +140 -0
  72. silica_core-0.7.0/silica/kernel/text/__init__.py +4 -0
  73. silica_core-0.7.0/silica/kernel/text/language.py +111 -0
  74. silica_core-0.7.0/silica/kernel/text/media.py +148 -0
  75. silica_core-0.7.0/silica/kernel/text/payload.py +160 -0
  76. silica_core-0.7.0/silica/kernel/text/sanitize.py +431 -0
  77. silica_core-0.7.0/silica/kernel/text/text.py +186 -0
  78. silica_core-0.7.0/silica/kernel/vault_manifest.py +626 -0
  79. silica_core-0.7.0/silica/kernel/write/__init__.py +4 -0
  80. silica_core-0.7.0/silica/kernel/write/frontmatter.py +158 -0
  81. silica_core-0.7.0/silica/kernel/write/ops.py +220 -0
  82. silica_core-0.7.0/silica/onboarding/__init__.py +3 -0
  83. silica_core-0.7.0/silica/onboarding/adopt.py +135 -0
  84. silica_core-0.7.0/silica/onboarding/checks.py +123 -0
  85. silica_core-0.7.0/silica/onboarding/setup_client.py +301 -0
  86. silica_core-0.7.0/silica/repl.py +199 -0
  87. silica_core-0.7.0/silica/skills/silica/SKILL.md +58 -0
  88. silica_core-0.7.0/silica/sources/__init__.py +4 -0
  89. silica_core-0.7.0/silica/sources/convert.py +2374 -0
  90. silica_core-0.7.0/silica/tools/__init__.py +189 -0
  91. silica_core-0.7.0/silica/tools/atomic.py +40 -0
  92. silica_core-0.7.0/silica/tools/tabular.py +470 -0
  93. silica_core-0.7.0/silica/ui/__init__.py +4 -0
  94. silica_core-0.7.0/silica/ui/connect.py +273 -0
  95. silica_core-0.7.0/silica/ui/mcp.py +137 -0
  96. silica_core-0.7.0/silica/update.py +226 -0
  97. silica_core-0.7.0/silica_core.egg-info/PKG-INFO +220 -0
  98. silica_core-0.7.0/silica_core.egg-info/SOURCES.txt +168 -0
  99. silica_core-0.7.0/silica_core.egg-info/dependency_links.txt +1 -0
  100. silica_core-0.7.0/silica_core.egg-info/entry_points.txt +2 -0
  101. silica_core-0.7.0/silica_core.egg-info/requires.txt +32 -0
  102. silica_core-0.7.0/silica_core.egg-info/scm_file_list.json +163 -0
  103. silica_core-0.7.0/silica_core.egg-info/scm_version.json +8 -0
  104. silica_core-0.7.0/silica_core.egg-info/top_level.txt +1 -0
  105. silica_core-0.7.0/tests/__init__.py +1 -0
  106. silica_core-0.7.0/tests/conftest.py +93 -0
  107. silica_core-0.7.0/tests/doc_factory.py +259 -0
  108. silica_core-0.7.0/tests/fixtures/__init__.py +1 -0
  109. silica_core-0.7.0/tests/fixtures/vault_factory.py +293 -0
  110. silica_core-0.7.0/tests/golden/__init__.py +2 -0
  111. silica_core-0.7.0/tests/golden/autolink_cases.json +58 -0
  112. silica_core-0.7.0/tests/golden/collision_threshold_cases.json +26 -0
  113. silica_core-0.7.0/tests/golden/keyphrase_cases.json +72 -0
  114. silica_core-0.7.0/tests/link_cases.py +44 -0
  115. silica_core-0.7.0/tests/llm_mocks.py +58 -0
  116. silica_core-0.7.0/tests/test_adr_link_resolution.py +45 -0
  117. silica_core-0.7.0/tests/test_ast_balance.py +16 -0
  118. silica_core-0.7.0/tests/test_atomic_write_bytes.py +71 -0
  119. silica_core-0.7.0/tests/test_clean_tag.py +27 -0
  120. silica_core-0.7.0/tests/test_code_lane_guards.py +169 -0
  121. silica_core-0.7.0/tests/test_codeast.py +721 -0
  122. silica_core-0.7.0/tests/test_codegraph.py +398 -0
  123. silica_core-0.7.0/tests/test_config_home.py +50 -0
  124. silica_core-0.7.0/tests/test_config_stt.py +85 -0
  125. silica_core-0.7.0/tests/test_config_ws.py +21 -0
  126. silica_core-0.7.0/tests/test_convert.py +1908 -0
  127. silica_core-0.7.0/tests/test_convert_child_reaping.py +74 -0
  128. silica_core-0.7.0/tests/test_core_contract.py +148 -0
  129. silica_core-0.7.0/tests/test_dominance.py +33 -0
  130. silica_core-0.7.0/tests/test_dotenv_layering.py +100 -0
  131. silica_core-0.7.0/tests/test_episodic_boundary.py +81 -0
  132. silica_core-0.7.0/tests/test_frontmatter_split.py +59 -0
  133. silica_core-0.7.0/tests/test_gitstate.py +125 -0
  134. silica_core-0.7.0/tests/test_gitstate_codegraph.py +64 -0
  135. silica_core-0.7.0/tests/test_ipynb.py +53 -0
  136. silica_core-0.7.0/tests/test_json_salvage.py +78 -0
  137. silica_core-0.7.0/tests/test_language.py +134 -0
  138. silica_core-0.7.0/tests/test_mcp_surface.py +119 -0
  139. silica_core-0.7.0/tests/test_media.py +188 -0
  140. silica_core-0.7.0/tests/test_mineru_error.py +92 -0
  141. silica_core-0.7.0/tests/test_no_shadowed_imports.py +64 -0
  142. silica_core-0.7.0/tests/test_payload_gate.py +100 -0
  143. silica_core-0.7.0/tests/test_plugin_manifests.py +96 -0
  144. silica_core-0.7.0/tests/test_recall_windows.py +54 -0
  145. silica_core-0.7.0/tests/test_relatedness_boundary.py +83 -0
  146. silica_core-0.7.0/tests/test_repl.py +78 -0
  147. silica_core-0.7.0/tests/test_repo_root.py +77 -0
  148. silica_core-0.7.0/tests/test_retrieval_check.py +79 -0
  149. silica_core-0.7.0/tests/test_setup_client.py +187 -0
  150. silica_core-0.7.0/tests/test_silicaignore.py +64 -0
  151. silica_core-0.7.0/tests/test_smoke.py +158 -0
  152. silica_core-0.7.0/tests/test_tabular.py +264 -0
  153. silica_core-0.7.0/tests/test_target_dir_resolution.py +50 -0
  154. silica_core-0.7.0/tests/test_text_seam.py +89 -0
  155. silica_core-0.7.0/tests/test_tokenizer_atoms.py +76 -0
  156. silica_core-0.7.0/tests/test_tokenizer_folding.py +42 -0
  157. silica_core-0.7.0/tests/test_tool_collapse_field.py +37 -0
  158. silica_core-0.7.0/tests/test_tool_name_contract.py +98 -0
  159. silica_core-0.7.0/tests/test_update.py +210 -0
  160. silica_core-0.7.0/tests/test_user_env_precedence.py +83 -0
  161. silica_core-0.7.0/tests/test_vault_conventions.py +255 -0
  162. silica_core-0.7.0/tests/test_vault_factory.py +151 -0
  163. silica_core-0.7.0/tests/test_vault_manifest.py +183 -0
  164. silica_core-0.7.0/tests/test_vault_pin_source.py +37 -0
  165. silica_core-0.7.0/tests/test_wikilink.py +57 -0
  166. silica_core-0.7.0/tests/test_wikilink_fast_path.py +189 -0
  167. silica_core-0.7.0/tests/test_write_boundary_regression.py +39 -0
  168. silica_core-0.7.0/tests/webassets.py +44 -0
  169. silica_core-0.7.0/uv.lock +1578 -0
  170. silica_core-0.7.0/vault.yaml +1 -0
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "silica-core",
3
+ "interface": {
4
+ "displayName": "Silica Core"
5
+ },
6
+ "plugins": [
7
+ {
8
+ "name": "silica-core",
9
+ "source": {
10
+ "source": "local",
11
+ "path": "./"
12
+ },
13
+ "policy": {
14
+ "installation": "AVAILABLE",
15
+ "authentication": "ON_INSTALL"
16
+ },
17
+ "category": "Productivity"
18
+ }
19
+ ]
20
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "silica-core",
3
+ "description": "Silica for Claude Code: retrieval tools over the folder you work in, no model in the loop.",
4
+ "owner": {
5
+ "name": "Alessandro Carosia"
6
+ },
7
+ "plugins": [
8
+ {
9
+ "name": "silica-core",
10
+ "source": "./",
11
+ "description": "files, search, read, code_pack, write_note over MCP; located evidence, never answers."
12
+ }
13
+ ]
14
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "silica-core",
3
+ "version": "0.6.1",
4
+ "description": "Retrieval tools for coding agents, no model in the loop: files, search, read, code_pack and write_note over the folder the session is opened in, served over MCP, plus a skill that teaches when to search and how to read coverage.",
5
+ "author": {
6
+ "name": "Alessandro Carosia"
7
+ },
8
+ "keywords": [
9
+ "retrieval",
10
+ "search",
11
+ "bm25",
12
+ "mcp",
13
+ "agents"
14
+ ],
15
+ "skills": "./silica/skills",
16
+ "mcpServers": "./mcp.json"
17
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "silica-core",
3
+ "version": "0.6.1",
4
+ "description": "Retrieval tools for coding agents, no model in the loop: files, search, read, code_pack and write_note over the folder the session is opened in, served over MCP, plus a skill that teaches when to search and how to read coverage.",
5
+ "author": {
6
+ "name": "Alessandro Carosia"
7
+ },
8
+ "keywords": [
9
+ "retrieval",
10
+ "search",
11
+ "bm25",
12
+ "mcp",
13
+ "agents"
14
+ ],
15
+ "skills": "./silica/skills",
16
+ "mcpServers": "./mcp.codex.json",
17
+ "interface": {
18
+ "displayName": "Silica Core",
19
+ "shortDescription": "Located evidence from your folder: search, read, inventory, code packs. No model, no memory lane.",
20
+ "developerName": "Alessandro Carosia"
21
+ }
22
+ }
@@ -0,0 +1,15 @@
1
+ # Allowlist, not a blocklist: the repo root holds .env, a 346 MB data/, dist/,
2
+ # .venv and five caches, and a blocklist chasing them is one `git add` away from
3
+ # leaking the next one into the build context.
4
+ *
5
+ !pyproject.toml
6
+ !README.md
7
+ !LICENSE
8
+ !LICENSE-COMMERCIAL.md
9
+ !silica/
10
+ # setuptools-scm reads it in the build stage to derive the version; without it
11
+ # the wheel installs as pyproject's fallback_version, 0.0.0, and the image can no
12
+ # longer say which build it is. Costs ~115 MB of context. If that matters more
13
+ # than the version does, drop this line and pass
14
+ # --build-arg SETUPTOOLS_SCM_PRETEND_VERSION_FOR_SILICA_CORE=$(git describe --tags)
15
+ !.git/
@@ -0,0 +1,77 @@
1
+ # Silica core: every variable the code reads. Copy to ~/.silica/.env, or export
2
+ # in the shell; an exported value wins over the file. Everything below is
3
+ # optional: with no file at all the five tools work, offline, on the folder
4
+ # the session is opened in.
5
+
6
+ # ---------------------------------------------------------------------------
7
+ # The root
8
+ # ---------------------------------------------------------------------------
9
+ # Silica serves the folder it is started in. SILICA_VAULT pins another root
10
+ # and is honoured ONLY when exported in the shell or passed as --vault: in
11
+ # this file it is ignored with a warning, because a pinned root belongs to
12
+ # the invocation, not to every session on the machine.
13
+ #
14
+ # export SILICA_VAULT=/path/to/folder
15
+
16
+ # ---------------------------------------------------------------------------
17
+ # The runtime directory
18
+ # ---------------------------------------------------------------------------
19
+ # `~/.silica` holds this file, `index/`, `tmp/` and `inbox/`. SILICA_HOME
20
+ # points all four somewhere else and, like SILICA_VAULT, is read from the
21
+ # shell alone: the variable that says where the config lives cannot live in
22
+ # the config. Use it to run a second tree on one machine without either
23
+ # inheriting the other's model, keys or index.
24
+ #
25
+ # export SILICA_HOME=~/.silica-core
26
+
27
+ # ---------------------------------------------------------------------------
28
+ # Converters (`silica import FILE`)
29
+ # ---------------------------------------------------------------------------
30
+ # PDF text layer: pdfium (default, one wheel, no OCR), or a binary you install
31
+ # and Silica calls: mineru (the only OCR path), docling, opendataloader.
32
+ # SILICA_PDF_PROVIDER=pdfium
33
+ # Languages mineru's OCR is given, comma-separated.
34
+ # SILICA_PDF_OCR_LANG=en,it,fr,de,es
35
+ # Root-relative folder the converted .md notes are written to.
36
+ # SILICA_INBOX_DIR=Inbox
37
+
38
+ # Audio and video are transcribed, not parsed: ffmpeg demuxes, then either an
39
+ # OpenAI-compatible /v1/audio/transcriptions endpoint (`endpoint`, the
40
+ # default; LM Studio, a local whisper server, or a hosted key) or a local
41
+ # whisper.cpp binary (`whispercpp`).
42
+ # SILICA_STT_PROVIDER=endpoint
43
+ # SILICA_STT_BASE_URL=http://localhost:1236/v1
44
+ # SILICA_STT_MODEL=whisper-1
45
+ # SILICA_STT_API_KEY=lm-studio
46
+ # SILICA_STT_LANG=auto
47
+ # SILICA_STT_WHISPERCPP_BIN=/path/to/whisper-cli
48
+ # SILICA_STT_WHISPERCPP_MODEL=/path/to/ggml-model.bin
49
+
50
+ # ---------------------------------------------------------------------------
51
+ # Embeddings extension (`silica index --embed`, `silica search --hybrid`)
52
+ # ---------------------------------------------------------------------------
53
+ # Off until a base URL is set. Any OpenAI-compatible /v1/embeddings endpoint:
54
+ # LM Studio, llama-server, Ollama, or a hosted key. One vector per document.
55
+ # Not part of the core contract: BM25 alone is what TOOLS.md promises.
56
+ # SILICA_EMBEDDING_BASE_URL=http://localhost:1234/v1
57
+ # SILICA_EMBEDDING_MODEL=text-embedding-qwen3-embedding-4b
58
+ # SILICA_EMBEDDING_API_KEY=lm-studio
59
+
60
+ # ---------------------------------------------------------------------------
61
+ # REPL (`silica repl`), the one surface with a model in the loop
62
+ # ---------------------------------------------------------------------------
63
+ # "provider/model" with a preset provider, or a bare model id served by
64
+ # SILICA_PROVIDER_BASE_URL. Presets and the key each one reads:
65
+ # openrouter OPENROUTER_API_KEY openai OPENAI_API_KEY
66
+ # deepseek DEEPSEEK_API_KEY groq GROQ_API_KEY
67
+ # mistral MISTRAL_API_KEY xai XAI_API_KEY
68
+ # gemini GEMINI_API_KEY lmstudio, ollama: local, no key
69
+ # SILICA_MODEL=openrouter/deepseek/deepseek-chat
70
+ # SILICA_PROVIDER_BASE_URL=http://localhost:1234/v1
71
+ # SILICA_PROVIDER_API_KEY=
72
+
73
+ # ---------------------------------------------------------------------------
74
+ # Obsidian bridge (`silica connect`, needs the [connect] extra)
75
+ # ---------------------------------------------------------------------------
76
+ # SILICA_WS_PORT=0
77
+ # SILICA_WS_TOKEN=
@@ -0,0 +1,4 @@
1
+ # Renders the "Sponsor" button on the repo, on issues and on PRs.
2
+ # github: needs Sponsors enabled at github.com/sponsors first, or the button stays hidden.
3
+ github: [kiycoh]
4
+ ko_fi: kiycoh
@@ -0,0 +1,26 @@
1
+ name: Bug report
2
+ description: Something Silica does that it should not.
3
+ labels: ["bug"]
4
+ body:
5
+ - type: textarea
6
+ id: what
7
+ attributes:
8
+ label: What happened
9
+ description: What you ran, what you expected, what you got instead. A minimal reproduction helps most.
10
+ validations:
11
+ required: true
12
+ - type: input
13
+ id: version
14
+ attributes:
15
+ label: Version and how you installed it
16
+ placeholder: "0.7.0, uv tool install silica-core"
17
+ validations:
18
+ required: true
19
+ - type: textarea
20
+ id: doctor
21
+ attributes:
22
+ label: silica doctor
23
+ description: Optional, and it answers most environment questions in one paste. It prints setting names, never their values.
24
+ render: text
25
+ validations:
26
+ required: false
@@ -0,0 +1,15 @@
1
+ # Questions and open-ended ideas belong in Discussions, security in the advisory
2
+ # flow: this file is what keeps them out of the tracker. blank_issues_enabled is
3
+ # false so every issue arrives through a form carrying a reproduction or a problem
4
+ # statement, because triage on a solo project is the scarce resource, not filing.
5
+ blank_issues_enabled: false
6
+ contact_links:
7
+ - name: Question, or something behaving in a way you did not expect
8
+ url: https://github.com/kiycoh/silica-core/discussions/categories/q-a
9
+ about: Ask in Q&A. Faster than an issue when you are not yet sure it is a bug.
10
+ - name: Idea, or a use case you want to talk through
11
+ url: https://github.com/kiycoh/silica-core/discussions/categories/ideas
12
+ about: For anything that is not yet a concrete feature request.
13
+ - name: Security vulnerability
14
+ url: https://github.com/kiycoh/silica-core/security/policy
15
+ about: Never open a public issue for a security problem. Read the policy first.
@@ -0,0 +1,18 @@
1
+ name: Feature request
2
+ description: Something Silica should do and does not.
3
+ labels: ["enhancement"]
4
+ body:
5
+ - type: textarea
6
+ id: problem
7
+ attributes:
8
+ label: The problem
9
+ description: What you were doing when you hit the wall. Describe the situation, not the solution you already have in mind.
10
+ validations:
11
+ required: true
12
+ - type: textarea
13
+ id: proposal
14
+ attributes:
15
+ label: What you would want instead
16
+ description: Silica takes the smallest diff that works, so a proposal that reuses a path already in the codebase lands where one that adds a layer does not.
17
+ validations:
18
+ required: true
@@ -0,0 +1,13 @@
1
+ ## What and why
2
+
3
+ <!-- One paragraph: what changes, and what made the obvious alternative wrong. -->
4
+
5
+ ## Checklist
6
+
7
+ - [ ] `uv run pytest` passes
8
+ - [ ] Non-trivial logic (a branch, a parser, a write path) leaves a runnable test behind
9
+ - [ ] No mutation reaches the vault outside the Injector FSM
10
+ - [ ] Code, comments and UI copy are English-only
11
+ - [ ] Conventional commits (`feat(scope): …`), one logical change each
12
+
13
+ By opening this PR you accept the license and relicensing terms in [CONTRIBUTING.md](https://github.com/kiycoh/silica-core/blob/main/CONTRIBUTING.md#license).
@@ -0,0 +1,31 @@
1
+ # Dependabot version updates.
2
+ # Two ecosystems match this repo: uv-managed Python deps (pyproject.toml + uv.lock)
3
+ # and the pinned actions in .github/workflows/release.yml.
4
+ # Commit prefixes (build / ci) map to cliff.toml's "^build|^ci" -> Build & CI section.
5
+ version: 2
6
+ updates:
7
+ - package-ecosystem: "uv"
8
+ directory: "/"
9
+ schedule:
10
+ interval: "weekly"
11
+ commit-message:
12
+ prefix: "build"
13
+ include: "scope"
14
+ open-pull-requests-limit: 5
15
+ # Minor/patch bumps arrive as one grouped PR to cut solo-maintainer noise;
16
+ # majors stay individual so breaking changes are reviewed on their own.
17
+ groups:
18
+ python-minor-patch:
19
+ patterns: ["*"]
20
+ update-types: ["minor", "patch"]
21
+
22
+ - package-ecosystem: "github-actions"
23
+ directory: "/"
24
+ schedule:
25
+ interval: "weekly"
26
+ commit-message:
27
+ prefix: "ci"
28
+ include: "scope"
29
+ groups:
30
+ actions:
31
+ patterns: ["*"]
@@ -0,0 +1,83 @@
1
+ name: ci
2
+
3
+ # The gates CONTRIBUTING already asks for, run where they can actually block:
4
+ # every PR and every push to main. A checklist the author ticks by hand is not
5
+ # a gate, and dependabot's weekly PRs have nothing checking them without this.
6
+
7
+ on:
8
+ push:
9
+ branches: [main]
10
+ pull_request:
11
+
12
+ permissions:
13
+ contents: read
14
+
15
+ concurrency:
16
+ # A superseded push on the same branch is dead work.
17
+ group: ci-${{ github.ref }}
18
+ cancel-in-progress: true
19
+
20
+ jobs:
21
+ test:
22
+ runs-on: ubuntu-latest
23
+ strategy:
24
+ fail-fast: false
25
+ matrix:
26
+ # The two versions pyproject claims in its classifiers. A claim no job
27
+ # checks is how a package promises 3.12 and ships broken on it.
28
+ python-version: ["3.11", "3.12"]
29
+ steps:
30
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
31
+
32
+ - uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
33
+ with:
34
+ python-version: ${{ matrix.python-version }}
35
+ enable-cache: true
36
+
37
+ # --locked fails when uv.lock has drifted from pyproject.toml, so a
38
+ # dependency edited without a relock dies here and not at a user's
39
+ # install. Extras: exactly the ones the suite reaches for with
40
+ # importorskip (fastapi/uvicorn, websockets, mcp).
41
+ # [rerank] stays out: 2 GB of torch to run tests that skip. There is no
42
+ # [pdf] extra any more — the mineru subprocess is patched in the suite.
43
+ - run: uv sync --locked --extra dev --extra connect --extra mcp
44
+
45
+ - run: uv run pytest -q
46
+
47
+ # Both are seconds and both were green when this file landed
48
+ # (2026-08-22: 9/9 contracts kept, 0 mypy errors over 206 files). They
49
+ # are here because a contract nothing re-checks is a comment.
50
+ - run: uv run lint-imports
51
+ - run: uv run mypy silica
52
+
53
+ # Third of the seconds-long gates, added 2026-09-03 at 0 findings after a
54
+ # cleanup of 158 unused imports. Narrow by config (F, E9 in pyproject):
55
+ # it blocks dead code, it does not arbitrate style.
56
+ - run: uv run ruff check silica tests
57
+
58
+ # The Dockerfile landed unbuilt by anything and went stale in place: the
59
+ # rename to silica-core walked past a build arg in .dockerignore that no job
60
+ # was exercising. An image nobody builds is a promise that breaks in the hand
61
+ # of the first person who tries it.
62
+ docker:
63
+ runs-on: ubuntu-latest
64
+ steps:
65
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
66
+ with:
67
+ # .dockerignore ships .git so setuptools-scm can name the wheel; the
68
+ # default shallow checkout carries no tags and every image would
69
+ # install as pyproject's fallback_version, 0.0.0.
70
+ fetch-depth: 0
71
+
72
+ - run: docker build -t silica-core:ci .
73
+
74
+ # Building proves the wheel resolves; it does not prove the image runs.
75
+ # One vault, one file, one search covers the parts that actually rot: the
76
+ # [mcp] extra, the HOME=/data relocation the index writes through, the
77
+ # entrypoint, and the /vault working directory.
78
+ - name: smoke
79
+ run: |
80
+ mkdir -p vault
81
+ printf '# Compaction\n\nLSM trees merge sorted runs on write.\n' > vault/notes.md
82
+ docker run --rm -v "$PWD/vault:/vault" silica-core:ci search compaction -k 1 | tee out.json
83
+ grep -q notes.md out.json
@@ -0,0 +1,67 @@
1
+ name: release-shim
2
+
3
+ # Publishes one of the redirect distributions: `silica-agent` (the 2026-08-23
4
+ # rename) or `silica-harness` (the 2026-09-08 rename), both pointing at
5
+ # `silica-core` (see packaging/*/pyproject.toml for why the old names are kept
6
+ # alive rather than deleted).
7
+ #
8
+ # Manual, not tag-driven: a shim's job is to point at a moving target, so one
9
+ # release keeps working for every silica-core that follows it. Run this only
10
+ # when a shim's own metadata changes, which should be close to never.
11
+ on:
12
+ workflow_dispatch:
13
+ inputs:
14
+ shim:
15
+ description: which redirect to publish
16
+ required: true
17
+ type: choice
18
+ options: [silica-harness, silica-agent]
19
+
20
+ permissions: {}
21
+
22
+ concurrency:
23
+ group: release-shim-${{ inputs.shim }}
24
+ cancel-in-progress: false
25
+
26
+ jobs:
27
+ publish:
28
+ runs-on: ubuntu-latest
29
+ # Same environment as release.yml, so PyPI's trusted publisher for the shim
30
+ # narrows to it the same way. NOTE: that publisher must name THIS
31
+ # repository (kiycoh/silica-core) and this workflow file — a publisher
32
+ # configured before a rename points at the old repository name and cannot
33
+ # match the OIDC claim.
34
+ environment:
35
+ name: pypi
36
+ url: https://pypi.org/p/${{ inputs.shim }}
37
+ permissions:
38
+ id-token: write # OIDC for PyPI Trusted Publishing (no stored token)
39
+ steps:
40
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
41
+
42
+ - uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
43
+ with:
44
+ python-version: "3.11"
45
+
46
+ # rm for the same reason release.yml does it: uv build writes a
47
+ # .gitignore into the output directory, and packages-dir uploads what it
48
+ # finds there.
49
+ - name: Build the shim
50
+ run: uv build --out-dir "$GITHUB_WORKSPACE/shim-dist" && rm -f "$GITHUB_WORKSPACE/shim-dist/.gitignore"
51
+ working-directory: packaging/${{ inputs.shim }}
52
+
53
+ # The only thing this distribution does is resolve to another one and
54
+ # keep the `silica` command working, so that is what gets checked before
55
+ # the irreversible step. A shim that installs but leaves no executable is
56
+ # the failure mode worth catching: nothing in the metadata shows it.
57
+ - name: Verify the shim resolves and still carries the command
58
+ run: |
59
+ uv venv /tmp/shim-check
60
+ VIRTUAL_ENV=/tmp/shim-check uv pip install "$GITHUB_WORKSPACE"/shim-dist/*.whl
61
+ VIRTUAL_ENV=/tmp/shim-check uv pip show silica-core > /dev/null
62
+ /tmp/shim-check/bin/silica --version
63
+
64
+ - name: Publish to PyPI
65
+ uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
66
+ with:
67
+ packages-dir: shim-dist
@@ -0,0 +1,87 @@
1
+ name: release
2
+
3
+ # Cut a release by pushing a SemVer tag, e.g.:
4
+ # git tag v0.3.0 && git push origin v0.3.0
5
+ # setuptools-scm reads the tag to stamp the version; git-cliff builds the notes.
6
+
7
+ on:
8
+ push:
9
+ tags:
10
+ - "v*"
11
+
12
+ permissions: {} # the one job below asks for what it needs; nothing inherits
13
+
14
+ concurrency:
15
+ # Never cancel a publish in flight: half a release is worse than a late one.
16
+ group: release-${{ github.ref }}
17
+ cancel-in-progress: false
18
+
19
+ jobs:
20
+ release:
21
+ runs-on: ubuntu-latest
22
+ # Scopes the Trusted Publishing OIDC to this environment (set the same name
23
+ # on the PyPI publisher for the narrowing to be real), and gives the repo
24
+ # one checkbox, required reviewers, to make a stray tag push wait for a
25
+ # human instead of shipping.
26
+ environment:
27
+ name: pypi
28
+ url: https://pypi.org/p/silica-core
29
+ permissions:
30
+ contents: write # create the GitHub Release
31
+ id-token: write # OIDC for PyPI Trusted Publishing (no stored token)
32
+ steps:
33
+ # Actions are pinned by commit, not by tag: this job holds a token that
34
+ # can publish to PyPI, and a tag is mutable. Dependabot (github-actions,
35
+ # weekly) bumps the pins and rewrites the version comment.
36
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
37
+ with:
38
+ fetch-depth: 0 # full history + tags for setuptools-scm and git-cliff
39
+
40
+ - uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
41
+ with:
42
+ python-version: "3.11"
43
+
44
+ - run: uv sync --locked --extra dev --extra connect --extra mcp
45
+
46
+ # A version on PyPI is burned even after a yank, so the irreversible step
47
+ # gets the gate: no green suite, no publish. ci.yml runs the same command
48
+ # on PRs; duplicated on purpose, because a tag can be pushed onto a commit
49
+ # no PR ever covered.
50
+ - name: Test before anything irreversible
51
+ run: uv run pytest -q
52
+
53
+ - name: Build sdist and wheel
54
+ # The rm is not tidiness: `files: dist/*` below attaches everything in
55
+ # here, and uv build writes a .gitignore that reached the v0.5.0
56
+ # release as an asset named default.gitignore. Excluding it there would
57
+ # mean listing the artifacts by name, which is a second way for the
58
+ # release to fail when one of them is not matched.
59
+ run: uv build && rm -f dist/.gitignore
60
+
61
+ - name: Verify built version matches the tag
62
+ run: ls -1 dist/ && uv run python -c "import pathlib,sys; t='${{ github.ref_name }}'.lstrip('v'); files=[p.name for p in pathlib.Path('dist').glob('*.whl')]; sys.exit(0 if any(t.replace('-','_') in f for f in files) else f'tag {t} not in {files}')"
63
+
64
+ - name: Verify the wheel ships the skill
65
+ # Guards the package-data config: `silica setup` copies SKILL.md out of
66
+ # the installed package, and a wheel that drops it fails at runtime.
67
+ run: |
68
+ unzip -l dist/*.whl | grep -q "silica/skills/silica/SKILL.md" || { echo "MISSING from wheel: SKILL.md"; exit 1; }
69
+
70
+ - name: Publish to PyPI
71
+ # Trusted Publishing via OIDC — the PyPI project must have this repo +
72
+ # workflow registered as a trusted publisher. No API token in secrets.
73
+ uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
74
+
75
+ - name: Generate release notes
76
+ uses: orhun/git-cliff-action@f50e11560dce63f7c33227798f90b924471a88b5 # v4.8.0
77
+ id: notes
78
+ with:
79
+ config: cliff.toml
80
+ args: --latest --strip header
81
+
82
+ - name: Publish GitHub release
83
+ uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2
84
+ with:
85
+ body: ${{ steps.notes.outputs.content }}
86
+ files: dist/*
87
+ fail_on_unmatched_files: true
@@ -0,0 +1,126 @@
1
+ # Python & Bytecode
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ *.sage.py
7
+
8
+ # Build & Packaging
9
+ build/
10
+ dist/
11
+ bin/
12
+ develop-eggs/
13
+ downloads/
14
+ eggs/
15
+ .eggs/
16
+ lib/
17
+ lib64/
18
+ parts/
19
+ sdist/
20
+ var/
21
+ wheels/
22
+ share/python-wheels/
23
+ *.egg-info/
24
+ .installed.cfg
25
+ *.egg
26
+ MANIFEST
27
+ silica/_version.py
28
+ *.manifest
29
+ *.spec
30
+ pip-log.txt
31
+ pip-delete-this-directory.txt
32
+ .pdm-plugins/
33
+ .pdm-python/
34
+ .pdm-build/
35
+ __pypackages__/
36
+
37
+ # Virtual Environments
38
+ .env
39
+ .venv
40
+ env/
41
+ venv/
42
+ ENV/
43
+ env.bak/
44
+ venv.bak/
45
+
46
+ # Testing, Linting & Coverage
47
+ .cache
48
+ .pytest_cache/
49
+ .mypy_cache/
50
+ .ruff_cache/
51
+ .tox/
52
+ .hatch/
53
+ .coverage
54
+ .coverage.*
55
+ htmlcov/
56
+ .htmlcov/
57
+ .nosenvy/
58
+ .noscript/
59
+ .nosetests/
60
+ nosetests.xml
61
+ coverage.xml
62
+ *.cover
63
+ *.py,cover
64
+ .hypothesis/
65
+ .run/
66
+ tests/fixtures/synthetic_vault/*
67
+ .import_linter_cache/
68
+ .grimp_cache/
69
+
70
+ # Editors & IDEs
71
+ .vscode/
72
+ .idea/
73
+ *.swp
74
+ *.swo
75
+ .spyderproject
76
+ .spyproject
77
+ .ropeproject
78
+ profile_default/
79
+ ipython_config.py
80
+ .ipynb_checkpoints
81
+
82
+ # OS Files
83
+ .DS_Store
84
+ Thumbs.db
85
+
86
+ # Documentation
87
+ docs/_build/
88
+ /site
89
+ /docs/*
90
+
91
+ # Silica & Agent Specific
92
+ # .agents/ is local agent tooling, except the Codex plugin marketplace, which
93
+ # Codex looks for at exactly .agents/plugins/marketplace.json.
94
+ /.agents/*
95
+ !/.agents/plugins/
96
+ .claude/
97
+ CLAUDE.md
98
+ .impeccable
99
+ /memory
100
+ .superpowers
101
+ .silica/
102
+ .silicaignore
103
+ .obsidian
104
+
105
+ # Databases & Locks
106
+ ruvector.db
107
+ agentdb.rvf
108
+ *.rvf.lock
109
+
110
+ # Evals & Benchmarks
111
+ evals/.oracle/
112
+ evals/golden/metrics.json
113
+ evals/*/metrics.*.json
114
+ bench/
115
+ # downloaded benchmark corpora (LongMemEval s is 265 MB)
116
+ data/
117
+
118
+ # Generated Files & Reports
119
+ graph.html
120
+ CONTEXT.md
121
+ PRODUCT.md
122
+ DESIGN.md
123
+
124
+ # Research corpus: papers pulled for design decisions, kept out of the tree.
125
+ # Silica still indexes them — .gitignore is deliberately not an index rule.
126
+ docs/research/