noetrail 0.10.0a1__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.
- noetrail-0.10.0a1/.github/CODEOWNERS +33 -0
- noetrail-0.10.0a1/.github/ISSUE_TEMPLATE/bug_report.yml +96 -0
- noetrail-0.10.0a1/.github/ISSUE_TEMPLATE/config.yml +15 -0
- noetrail-0.10.0a1/.github/ISSUE_TEMPLATE/documentation.yml +75 -0
- noetrail-0.10.0a1/.github/ISSUE_TEMPLATE/feature_request.yml +77 -0
- noetrail-0.10.0a1/.github/PULL_REQUEST_TEMPLATE.md +47 -0
- noetrail-0.10.0a1/.github/dependabot.yml +19 -0
- noetrail-0.10.0a1/.github/workflows/ci.yml +153 -0
- noetrail-0.10.0a1/.github/workflows/codeql.yml +53 -0
- noetrail-0.10.0a1/.github/workflows/deploy-zeroclaw.yml +49 -0
- noetrail-0.10.0a1/.github/workflows/release.yml +172 -0
- noetrail-0.10.0a1/.gitignore +34 -0
- noetrail-0.10.0a1/.knowledge/SPEC.md +674 -0
- noetrail-0.10.0a1/.knowledge/config.yaml +25 -0
- noetrail-0.10.0a1/.knowledge/packs/books/book.md +5 -0
- noetrail-0.10.0a1/.knowledge/packs/books/pack.yaml +32 -0
- noetrail-0.10.0a1/.knowledge/packs/knowledge-core/pack.yaml +230 -0
- noetrail-0.10.0a1/.knowledge/relation-types.yaml +18 -0
- noetrail-0.10.0a1/.knowledge/schemas/entry.schema.json +294 -0
- noetrail-0.10.0a1/.knowledge/templates/bookmark.md +27 -0
- noetrail-0.10.0a1/.knowledge/templates/experience.md +17 -0
- noetrail-0.10.0a1/.knowledge/templates/imported-note.md +18 -0
- noetrail-0.10.0a1/.knowledge/templates/memory.md +17 -0
- noetrail-0.10.0a1/.knowledge/templates/place.md +17 -0
- noetrail-0.10.0a1/.knowledge/templates/product.md +17 -0
- noetrail-0.10.0a1/.knowledge/templates/recipe.md +27 -0
- noetrail-0.10.0a1/.knowledge/templates/thought.md +17 -0
- noetrail-0.10.0a1/AGENTS.md +124 -0
- noetrail-0.10.0a1/CHANGELOG.md +543 -0
- noetrail-0.10.0a1/CODE_OF_CONDUCT.md +137 -0
- noetrail-0.10.0a1/CONTRIBUTING.md +145 -0
- noetrail-0.10.0a1/LICENSE +201 -0
- noetrail-0.10.0a1/MANIFEST.in +58 -0
- noetrail-0.10.0a1/Makefile +67 -0
- noetrail-0.10.0a1/PKG-INFO +363 -0
- noetrail-0.10.0a1/README.md +334 -0
- noetrail-0.10.0a1/ROADMAP.md +84 -0
- noetrail-0.10.0a1/SECURITY.md +100 -0
- noetrail-0.10.0a1/SUPPORT.md +30 -0
- noetrail-0.10.0a1/demo/README.md +39 -0
- noetrail-0.10.0a1/demo/config/packs/travel/pack.yaml +26 -0
- noetrail-0.10.0a1/demo/data/imports/raw/markdown/reading-list.md +4 -0
- noetrail-0.10.0a1/demo/data/imports/work/.gitkeep +1 -0
- noetrail-0.10.0a1/demo/data/trash/.gitkeep +1 -0
- noetrail-0.10.0a1/demo/data/vault/.locks/.gitkeep +1 -0
- noetrail-0.10.0a1/demo/data/vault/custom/travel/destination/2026-01-01--azure-harbor--22222222.md +24 -0
- noetrail-0.10.0a1/demo/data/vault/notes/2026-01-01--welcome-to-noetrail--11111111.md +21 -0
- noetrail-0.10.0a1/demo/session.sh +70 -0
- noetrail-0.10.0a1/deploy/zeroclaw/AGENTS.md +161 -0
- noetrail-0.10.0a1/deploy/zeroclaw/Containerfile.bookmark-fetcher +23 -0
- noetrail-0.10.0a1/deploy/zeroclaw/bookmark-fetcher-deployment.example.yaml +77 -0
- noetrail-0.10.0a1/deploy/zeroclaw/bookmark-fetcher-network-policy.example.yaml +83 -0
- noetrail-0.10.0a1/deploy/zeroclaw/security-profiles.example.toml +250 -0
- noetrail-0.10.0a1/docs/adr/0001-core-and-schema-packs.md +254 -0
- noetrail-0.10.0a1/docs/adr/0002-noetrail-name-and-compatibility.md +65 -0
- noetrail-0.10.0a1/docs/adr/0003-in-process-reads.md +123 -0
- noetrail-0.10.0a1/docs/adr/0004-no-search-index.md +109 -0
- noetrail-0.10.0a1/docs/adr/0005-lexical-bm25-index.md +156 -0
- noetrail-0.10.0a1/docs/adr/0006-relation-level-valid-time.md +194 -0
- noetrail-0.10.0a1/docs/adr/0007-hybrid-retrieval-default.md +104 -0
- noetrail-0.10.0a1/docs/adr/0008-word-form-fallback.md +57 -0
- noetrail-0.10.0a1/docs/adr/README.md +24 -0
- noetrail-0.10.0a1/docs/ai-authorship.md +85 -0
- noetrail-0.10.0a1/docs/alpha-pilot.md +44 -0
- noetrail-0.10.0a1/docs/architecture.md +321 -0
- noetrail-0.10.0a1/docs/assets/demo.svg +77 -0
- noetrail-0.10.0a1/docs/assets/demo.txt +72 -0
- noetrail-0.10.0a1/docs/assets/noetrail-lockup.svg +12 -0
- noetrail-0.10.0a1/docs/assets/noetrail-logo.md +24 -0
- noetrail-0.10.0a1/docs/assets/noetrail-mark-currentcolor.svg +10 -0
- noetrail-0.10.0a1/docs/assets/noetrail-mark-small.svg +10 -0
- noetrail-0.10.0a1/docs/assets/noetrail-mark.svg +10 -0
- noetrail-0.10.0a1/docs/assets/valid-time-dark.svg +38 -0
- noetrail-0.10.0a1/docs/assets/valid-time-light.svg +38 -0
- noetrail-0.10.0a1/docs/backup-restore.md +100 -0
- noetrail-0.10.0a1/docs/embeddings.md +135 -0
- noetrail-0.10.0a1/docs/importing.md +201 -0
- noetrail-0.10.0a1/docs/installation.md +158 -0
- noetrail-0.10.0a1/docs/integrations/mcp-clients.md +189 -0
- noetrail-0.10.0a1/docs/integrations/zeroclaw-security.md +272 -0
- noetrail-0.10.0a1/docs/integrations/zeroclaw-setup.md +376 -0
- noetrail-0.10.0a1/docs/internal/decision-log.md +95 -0
- noetrail-0.10.0a1/docs/knowledge-maintenance.md +52 -0
- noetrail-0.10.0a1/docs/layout.md +111 -0
- noetrail-0.10.0a1/docs/limits.md +364 -0
- noetrail-0.10.0a1/docs/privacy.md +127 -0
- noetrail-0.10.0a1/docs/publication-readiness.md +106 -0
- noetrail-0.10.0a1/docs/quickstart.md +250 -0
- noetrail-0.10.0a1/docs/releases/0.10.0a1.md +98 -0
- noetrail-0.10.0a1/docs/releasing.md +239 -0
- noetrail-0.10.0a1/docs/retrieval-evaluation.md +112 -0
- noetrail-0.10.0a1/docs/saved-views.md +37 -0
- noetrail-0.10.0a1/docs/schema-packs.md +253 -0
- noetrail-0.10.0a1/docs/versioning.md +26 -0
- noetrail-0.10.0a1/pyproject.toml +168 -0
- noetrail-0.10.0a1/setup.cfg +4 -0
- noetrail-0.10.0a1/skills/capture-knowledge/SKILL.md +316 -0
- noetrail-0.10.0a1/skills/capture-knowledge/agents/openai.yaml +4 -0
- noetrail-0.10.0a1/skills/fetch-bookmark-metadata/SKILL.md +32 -0
- noetrail-0.10.0a1/skills/fetch-bookmark-metadata/agents/openai.yaml +4 -0
- noetrail-0.10.0a1/skills/import-knowledge/SKILL.md +86 -0
- noetrail-0.10.0a1/skills/import-knowledge/agents/openai.yaml +4 -0
- noetrail-0.10.0a1/skills/manage-trash/SKILL.md +93 -0
- noetrail-0.10.0a1/skills/manage-trash/agents/openai.yaml +4 -0
- noetrail-0.10.0a1/skills/review-knowledge/SKILL.md +94 -0
- noetrail-0.10.0a1/skills/review-knowledge/agents/openai.yaml +4 -0
- noetrail-0.10.0a1/skills/save-bookmark/SKILL.md +161 -0
- noetrail-0.10.0a1/skills/save-bookmark/agents/openai.yaml +4 -0
- noetrail-0.10.0a1/src/noetrail/__init__.py +7 -0
- noetrail-0.10.0a1/src/noetrail/attachments.py +320 -0
- noetrail-0.10.0a1/src/noetrail/basic_memory.py +129 -0
- noetrail-0.10.0a1/src/noetrail/body.py +222 -0
- noetrail-0.10.0a1/src/noetrail/bookmark_fetcher.py +1159 -0
- noetrail-0.10.0a1/src/noetrail/cli.py +1020 -0
- noetrail-0.10.0a1/src/noetrail/commands/__init__.py +7 -0
- noetrail-0.10.0a1/src/noetrail/commands/capture.py +538 -0
- noetrail-0.10.0a1/src/noetrail/commands/curate.py +295 -0
- noetrail-0.10.0a1/src/noetrail/commands/edit.py +899 -0
- noetrail-0.10.0a1/src/noetrail/commands/importer.py +334 -0
- noetrail-0.10.0a1/src/noetrail/commands/maintenance.py +785 -0
- noetrail-0.10.0a1/src/noetrail/commands/query.py +903 -0
- noetrail-0.10.0a1/src/noetrail/commands/quickstart.py +239 -0
- noetrail-0.10.0a1/src/noetrail/commands/review.py +440 -0
- noetrail-0.10.0a1/src/noetrail/commands/vault_import.py +984 -0
- noetrail-0.10.0a1/src/noetrail/commands/views.py +69 -0
- noetrail-0.10.0a1/src/noetrail/constants.py +356 -0
- noetrail-0.10.0a1/src/noetrail/deadline.py +34 -0
- noetrail-0.10.0a1/src/noetrail/entries.py +230 -0
- noetrail-0.10.0a1/src/noetrail/errors.py +107 -0
- noetrail-0.10.0a1/src/noetrail/evidence.py +96 -0
- noetrail-0.10.0a1/src/noetrail/frontmatter.py +716 -0
- noetrail-0.10.0a1/src/noetrail/index.py +1028 -0
- noetrail-0.10.0a1/src/noetrail/jsonrpc.py +92 -0
- noetrail-0.10.0a1/src/noetrail/layout.py +344 -0
- noetrail-0.10.0a1/src/noetrail/mcp.py +2665 -0
- noetrail-0.10.0a1/src/noetrail/mcp_protocol.py +99 -0
- noetrail-0.10.0a1/src/noetrail/migrations.py +359 -0
- noetrail-0.10.0a1/src/noetrail/normalize.py +121 -0
- noetrail-0.10.0a1/src/noetrail/obsidian.py +339 -0
- noetrail-0.10.0a1/src/noetrail/payloads.py +57 -0
- noetrail-0.10.0a1/src/noetrail/provenance.py +217 -0
- noetrail-0.10.0a1/src/noetrail/relations.py +129 -0
- noetrail-0.10.0a1/src/noetrail/schema.py +1143 -0
- noetrail-0.10.0a1/src/noetrail/search.py +366 -0
- noetrail-0.10.0a1/src/noetrail/store.py +263 -0
- noetrail-0.10.0a1/src/noetrail/temporal.py +469 -0
- noetrail-0.10.0a1/src/noetrail/validation.py +574 -0
- noetrail-0.10.0a1/src/noetrail/vectors.py +271 -0
- noetrail-0.10.0a1/src/noetrail/version.py +19 -0
- noetrail-0.10.0a1/src/noetrail/views.py +287 -0
- noetrail-0.10.0a1/src/noetrail.egg-info/PKG-INFO +363 -0
- noetrail-0.10.0a1/src/noetrail.egg-info/SOURCES.txt +221 -0
- noetrail-0.10.0a1/src/noetrail.egg-info/dependency_links.txt +1 -0
- noetrail-0.10.0a1/src/noetrail.egg-info/entry_points.txt +7 -0
- noetrail-0.10.0a1/src/noetrail.egg-info/top_level.txt +1 -0
- noetrail-0.10.0a1/tests/__init__.py +66 -0
- noetrail-0.10.0a1/tests/test_absent_type.py +125 -0
- noetrail-0.10.0a1/tests/test_backup_restore.py +72 -0
- noetrail-0.10.0a1/tests/test_body_headings.py +151 -0
- noetrail-0.10.0a1/tests/test_bookmark_fetch_mcp.py +316 -0
- noetrail-0.10.0a1/tests/test_bookmark_fetcher_addresses.py +219 -0
- noetrail-0.10.0a1/tests/test_bookmark_fetcher_redirects.py +535 -0
- noetrail-0.10.0a1/tests/test_builtin_schema.py +361 -0
- noetrail-0.10.0a1/tests/test_cli.py +2765 -0
- noetrail-0.10.0a1/tests/test_coverage_tool.py +178 -0
- noetrail-0.10.0a1/tests/test_curate.py +168 -0
- noetrail-0.10.0a1/tests/test_custom_types.py +350 -0
- noetrail-0.10.0a1/tests/test_demo.py +74 -0
- noetrail-0.10.0a1/tests/test_demo_recording.py +116 -0
- noetrail-0.10.0a1/tests/test_documentation.py +495 -0
- noetrail-0.10.0a1/tests/test_everyday_questions.py +50 -0
- noetrail-0.10.0a1/tests/test_foreign_formats.py +232 -0
- noetrail-0.10.0a1/tests/test_frontmatter.py +315 -0
- noetrail-0.10.0a1/tests/test_git_boundary.py +65 -0
- noetrail-0.10.0a1/tests/test_governance.py +281 -0
- noetrail-0.10.0a1/tests/test_history_check.py +141 -0
- noetrail-0.10.0a1/tests/test_hybrid_rank.py +174 -0
- noetrail-0.10.0a1/tests/test_in_process.py +226 -0
- noetrail-0.10.0a1/tests/test_initialization.py +148 -0
- noetrail-0.10.0a1/tests/test_jsonrpc.py +79 -0
- noetrail-0.10.0a1/tests/test_layout.py +507 -0
- noetrail-0.10.0a1/tests/test_locking.py +507 -0
- noetrail-0.10.0a1/tests/test_malformed_frontmatter.py +184 -0
- noetrail-0.10.0a1/tests/test_markdown_import.py +183 -0
- noetrail-0.10.0a1/tests/test_mcp.py +1800 -0
- noetrail-0.10.0a1/tests/test_migrations.py +230 -0
- noetrail-0.10.0a1/tests/test_packaging.py +548 -0
- noetrail-0.10.0a1/tests/test_provenance.py +478 -0
- noetrail-0.10.0a1/tests/test_quickstart.py +128 -0
- noetrail-0.10.0a1/tests/test_read_deadline.py +52 -0
- noetrail-0.10.0a1/tests/test_release_consistency.py +88 -0
- noetrail-0.10.0a1/tests/test_retrieval_quality.py +157 -0
- noetrail-0.10.0a1/tests/test_retype.py +223 -0
- noetrail-0.10.0a1/tests/test_schema.py +465 -0
- noetrail-0.10.0a1/tests/test_search_evidence.py +46 -0
- noetrail-0.10.0a1/tests/test_search_index.py +688 -0
- noetrail-0.10.0a1/tests/test_supply_chain.py +190 -0
- noetrail-0.10.0a1/tests/test_temporal.py +933 -0
- noetrail-0.10.0a1/tests/test_vault_import.py +625 -0
- noetrail-0.10.0a1/tests/test_vault_index.py +304 -0
- noetrail-0.10.0a1/tests/test_vector_rerank.py +337 -0
- noetrail-0.10.0a1/tests/test_views.py +494 -0
- noetrail-0.10.0a1/tests/test_word_forms.py +108 -0
- noetrail-0.10.0a1/tests/test_zeroclaw_candidate.py +94 -0
- noetrail-0.10.0a1/tools/bookmark_fetch_mcp.py +18 -0
- noetrail-0.10.0a1/tools/check_git_boundary.py +122 -0
- noetrail-0.10.0a1/tools/check_history.py +180 -0
- noetrail-0.10.0a1/tools/check_release_consistency.py +105 -0
- noetrail-0.10.0a1/tools/check_reproducible.py +249 -0
- noetrail-0.10.0a1/tools/check_secrets.py +102 -0
- noetrail-0.10.0a1/tools/coverage.py +526 -0
- noetrail-0.10.0a1/tools/generate_sbom.py +248 -0
- noetrail-0.10.0a1/tools/know.py +18 -0
- noetrail-0.10.0a1/tools/knowledge_mcp.py +18 -0
- noetrail-0.10.0a1/tools/measure_questions.py +131 -0
- noetrail-0.10.0a1/tools/measure_retrieval.py +209 -0
- noetrail-0.10.0a1/tools/measure_search.py +455 -0
- noetrail-0.10.0a1/tools/question_set.json +828 -0
- noetrail-0.10.0a1/tools/release_acceptance.py +332 -0
- noetrail-0.10.0a1/tools/render_terminal_svg.py +280 -0
- noetrail-0.10.0a1/tools/retrieval_set.json +359 -0
- noetrail-0.10.0a1/tools/word_form_set.json +40 -0
- noetrail-0.10.0a1/tools/zeroclaw_candidate.py +40 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Review ownership. Noetrail has one maintainer, so a single catch-all rule
|
|
2
|
+
# would be enough; the paths below are listed separately because they are the
|
|
3
|
+
# ones where an unreviewed change is expensive, and because this file should
|
|
4
|
+
# still say something useful when there is more than one owner.
|
|
5
|
+
#
|
|
6
|
+
# CODEOWNERS only requests reviews. Requiring them is a branch-protection
|
|
7
|
+
# setting on `main`, which is configured in the repository settings, not here.
|
|
8
|
+
|
|
9
|
+
* @patsch1
|
|
10
|
+
|
|
11
|
+
# On-disk format, migrations, and the code that decides what a path may be.
|
|
12
|
+
/src/noetrail/migrations.py @patsch1
|
|
13
|
+
/src/noetrail/layout.py @patsch1
|
|
14
|
+
/src/noetrail/schema.py @patsch1
|
|
15
|
+
/.knowledge/ @patsch1
|
|
16
|
+
|
|
17
|
+
# Agent-facing boundaries: the MCP surface and the isolated fetcher.
|
|
18
|
+
/src/noetrail/mcp.py @patsch1
|
|
19
|
+
/src/noetrail/mcp_protocol.py @patsch1
|
|
20
|
+
/src/noetrail/bookmark_fetcher.py @patsch1
|
|
21
|
+
|
|
22
|
+
# Supply chain and publication: workflows, packaging metadata, and the
|
|
23
|
+
# scripts a release is checked with.
|
|
24
|
+
/.github/ @patsch1
|
|
25
|
+
/pyproject.toml @patsch1
|
|
26
|
+
/MANIFEST.in @patsch1
|
|
27
|
+
/tools/ @patsch1
|
|
28
|
+
|
|
29
|
+
# Governance and security promises.
|
|
30
|
+
/SECURITY.md @patsch1
|
|
31
|
+
/CODE_OF_CONDUCT.md @patsch1
|
|
32
|
+
/CONTRIBUTING.md @patsch1
|
|
33
|
+
/LICENSE @patsch1
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: Something behaves differently than documented, or fails.
|
|
3
|
+
title: "bug: "
|
|
4
|
+
labels: ["bug"]
|
|
5
|
+
body:
|
|
6
|
+
- type: markdown
|
|
7
|
+
attributes:
|
|
8
|
+
value: |
|
|
9
|
+
SUPPORT.md asks for the environment and a `noetrail doctor` report with
|
|
10
|
+
every issue. This form requires it, because a bug report without it
|
|
11
|
+
usually costs one round trip before anything can be looked at.
|
|
12
|
+
|
|
13
|
+
Use synthetic data. Never paste a real vault entry, export,
|
|
14
|
+
attachment, URL with personal content, token, or infrastructure
|
|
15
|
+
detail. Redact absolute paths that contain names.
|
|
16
|
+
- type: checkboxes
|
|
17
|
+
id: preflight
|
|
18
|
+
attributes:
|
|
19
|
+
label: Before reporting
|
|
20
|
+
options:
|
|
21
|
+
- label: I searched the existing open and closed issues.
|
|
22
|
+
required: true
|
|
23
|
+
- label: I can reproduce this with synthetic data in a temporary vault, or I explain below why not.
|
|
24
|
+
required: true
|
|
25
|
+
- label: This report contains no personal vault content, credentials, or private infrastructure details.
|
|
26
|
+
required: true
|
|
27
|
+
- label: This is not a security vulnerability. Those go to the private channel in SECURITY.md.
|
|
28
|
+
required: true
|
|
29
|
+
- type: input
|
|
30
|
+
id: version
|
|
31
|
+
attributes:
|
|
32
|
+
label: Noetrail version
|
|
33
|
+
description: Output of `noetrail --version`.
|
|
34
|
+
placeholder: "noetrail 0.10.0a1"
|
|
35
|
+
validations:
|
|
36
|
+
required: true
|
|
37
|
+
- type: input
|
|
38
|
+
id: python
|
|
39
|
+
attributes:
|
|
40
|
+
label: Python version
|
|
41
|
+
description: Output of `python3 -V`.
|
|
42
|
+
placeholder: "Python 3.13.2"
|
|
43
|
+
validations:
|
|
44
|
+
required: true
|
|
45
|
+
- type: input
|
|
46
|
+
id: os
|
|
47
|
+
attributes:
|
|
48
|
+
label: Operating system
|
|
49
|
+
description: Name and version, plus the filesystem if the vault is not on local storage.
|
|
50
|
+
placeholder: "Debian 13, ext4"
|
|
51
|
+
validations:
|
|
52
|
+
required: true
|
|
53
|
+
- type: dropdown
|
|
54
|
+
id: surface
|
|
55
|
+
attributes:
|
|
56
|
+
label: Command surface
|
|
57
|
+
options:
|
|
58
|
+
- CLI
|
|
59
|
+
- Noetrail MCP
|
|
60
|
+
- bookmark fetcher
|
|
61
|
+
- both CLI and MCP
|
|
62
|
+
validations:
|
|
63
|
+
required: true
|
|
64
|
+
- type: textarea
|
|
65
|
+
id: doctor
|
|
66
|
+
attributes:
|
|
67
|
+
label: "`noetrail doctor` output"
|
|
68
|
+
description: Run `noetrail doctor` against the affected instance and paste the JSON report unchanged, except for paths you need to redact.
|
|
69
|
+
render: json
|
|
70
|
+
validations:
|
|
71
|
+
required: true
|
|
72
|
+
- type: textarea
|
|
73
|
+
id: reproduction
|
|
74
|
+
attributes:
|
|
75
|
+
label: Steps to reproduce
|
|
76
|
+
description: The exact commands, in order, starting from a state a reader can create.
|
|
77
|
+
placeholder: |
|
|
78
|
+
1. noetrail --data-root "$T/data" --config-root "$T/config" init
|
|
79
|
+
2. noetrail ... capture --type thought --title "synthetic" --text "synthetic"
|
|
80
|
+
3. noetrail ... search synthetic
|
|
81
|
+
validations:
|
|
82
|
+
required: true
|
|
83
|
+
- type: textarea
|
|
84
|
+
id: expected
|
|
85
|
+
attributes:
|
|
86
|
+
label: Expected and actual result
|
|
87
|
+
description: What you expected, what happened, and the sanitized error or exit code.
|
|
88
|
+
validations:
|
|
89
|
+
required: true
|
|
90
|
+
- type: textarea
|
|
91
|
+
id: context
|
|
92
|
+
attributes:
|
|
93
|
+
label: Anything else
|
|
94
|
+
description: Schema packs in use, vault size, MCP client, container deployment. Optional.
|
|
95
|
+
validations:
|
|
96
|
+
required: false
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Blank issues are disabled on purpose: the three forms exist so that a report
|
|
2
|
+
# arrives with the version, the interpreter, the operating system, and a
|
|
3
|
+
# `noetrail doctor` report already in it, which SUPPORT.md asks for and a free
|
|
4
|
+
# text box does not enforce.
|
|
5
|
+
blank_issues_enabled: false
|
|
6
|
+
contact_links:
|
|
7
|
+
- name: Question or idea
|
|
8
|
+
url: https://github.com/patsch1/noetrail/discussions
|
|
9
|
+
about: Usage questions, agent setups, and open-ended ideas belong in Discussions, not in the issue tracker.
|
|
10
|
+
- name: Report a security vulnerability
|
|
11
|
+
url: https://github.com/patsch1/noetrail/security/advisories/new
|
|
12
|
+
about: Never file a vulnerability as a public issue. Use the private advisory form; SECURITY.md states the response times.
|
|
13
|
+
- name: Support and what to include
|
|
14
|
+
url: https://github.com/patsch1/noetrail/blob/main/SUPPORT.md
|
|
15
|
+
about: What this project does and does not support, and how to sanitize a report before sending it.
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
name: Documentation problem
|
|
2
|
+
description: A documented step is wrong, missing, unclear, or out of date.
|
|
3
|
+
title: "docs: "
|
|
4
|
+
labels: ["documentation"]
|
|
5
|
+
body:
|
|
6
|
+
- type: markdown
|
|
7
|
+
attributes:
|
|
8
|
+
value: |
|
|
9
|
+
The shell blocks in `README.md` and `docs/quickstart.md` are executed
|
|
10
|
+
by the test suite, so a failing block there is a real defect. Blocks in
|
|
11
|
+
other documents are not, and a report is the only way they get fixed.
|
|
12
|
+
|
|
13
|
+
Redact absolute paths that contain personal names.
|
|
14
|
+
- type: checkboxes
|
|
15
|
+
id: preflight
|
|
16
|
+
attributes:
|
|
17
|
+
label: Before reporting
|
|
18
|
+
options:
|
|
19
|
+
- label: I searched the existing open and closed issues.
|
|
20
|
+
required: true
|
|
21
|
+
- label: This report contains no personal vault content or credentials.
|
|
22
|
+
required: true
|
|
23
|
+
- type: input
|
|
24
|
+
id: document
|
|
25
|
+
attributes:
|
|
26
|
+
label: Document
|
|
27
|
+
description: Repository path, and the heading or line if you have it.
|
|
28
|
+
placeholder: "docs/quickstart.md, section 'Import Markdown'"
|
|
29
|
+
validations:
|
|
30
|
+
required: true
|
|
31
|
+
- type: input
|
|
32
|
+
id: version
|
|
33
|
+
attributes:
|
|
34
|
+
label: Noetrail version
|
|
35
|
+
description: Output of `noetrail --version`. Documentation is versioned with the program.
|
|
36
|
+
placeholder: "noetrail 0.10.0a1"
|
|
37
|
+
validations:
|
|
38
|
+
required: true
|
|
39
|
+
- type: input
|
|
40
|
+
id: python
|
|
41
|
+
attributes:
|
|
42
|
+
label: Python version
|
|
43
|
+
description: Output of `python3 -V`.
|
|
44
|
+
placeholder: "Python 3.13.2"
|
|
45
|
+
validations:
|
|
46
|
+
required: true
|
|
47
|
+
- type: input
|
|
48
|
+
id: os
|
|
49
|
+
attributes:
|
|
50
|
+
label: Operating system
|
|
51
|
+
placeholder: "Ubuntu 24.04"
|
|
52
|
+
validations:
|
|
53
|
+
required: true
|
|
54
|
+
- type: textarea
|
|
55
|
+
id: doctor
|
|
56
|
+
attributes:
|
|
57
|
+
label: "`noetrail doctor` output"
|
|
58
|
+
description: Most documentation problems are really a mismatch between the documented layout and the actual one. This report shows which it is.
|
|
59
|
+
render: json
|
|
60
|
+
validations:
|
|
61
|
+
required: true
|
|
62
|
+
- type: textarea
|
|
63
|
+
id: problem
|
|
64
|
+
attributes:
|
|
65
|
+
label: What is wrong
|
|
66
|
+
description: Quote the documented text, then say what actually happens or what is missing. Include the command and its sanitized output if a documented step failed.
|
|
67
|
+
validations:
|
|
68
|
+
required: true
|
|
69
|
+
- type: textarea
|
|
70
|
+
id: suggestion
|
|
71
|
+
attributes:
|
|
72
|
+
label: Suggested wording
|
|
73
|
+
description: Optional. A concrete replacement is usually faster than a discussion.
|
|
74
|
+
validations:
|
|
75
|
+
required: false
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
name: Feature request
|
|
2
|
+
description: Propose a bounded change in behavior.
|
|
3
|
+
title: "feature: "
|
|
4
|
+
labels: ["enhancement"]
|
|
5
|
+
body:
|
|
6
|
+
- type: markdown
|
|
7
|
+
attributes:
|
|
8
|
+
value: |
|
|
9
|
+
Noetrail is a one-person project before `1.0`. A proposal that names
|
|
10
|
+
the problem, the smallest change that solves it, and what it would
|
|
11
|
+
cost has a much better chance than a list of wishes.
|
|
12
|
+
|
|
13
|
+
ROADMAP.md lists what is planned and what is deliberately out of
|
|
14
|
+
scope. Please check it first.
|
|
15
|
+
- type: checkboxes
|
|
16
|
+
id: preflight
|
|
17
|
+
attributes:
|
|
18
|
+
label: Before proposing
|
|
19
|
+
options:
|
|
20
|
+
- label: I searched the existing open and closed issues.
|
|
21
|
+
required: true
|
|
22
|
+
- label: I read ROADMAP.md and this is not already listed as a non-goal.
|
|
23
|
+
required: true
|
|
24
|
+
- label: This request contains no personal vault content or credentials.
|
|
25
|
+
required: true
|
|
26
|
+
- type: input
|
|
27
|
+
id: version
|
|
28
|
+
attributes:
|
|
29
|
+
label: Noetrail version
|
|
30
|
+
description: Output of `noetrail --version`, so the proposal is read against the right behavior.
|
|
31
|
+
placeholder: "noetrail 0.10.0a1"
|
|
32
|
+
validations:
|
|
33
|
+
required: true
|
|
34
|
+
- type: input
|
|
35
|
+
id: python
|
|
36
|
+
attributes:
|
|
37
|
+
label: Python version
|
|
38
|
+
description: Output of `python3 -V`.
|
|
39
|
+
placeholder: "Python 3.13.2"
|
|
40
|
+
validations:
|
|
41
|
+
required: true
|
|
42
|
+
- type: input
|
|
43
|
+
id: os
|
|
44
|
+
attributes:
|
|
45
|
+
label: Operating system
|
|
46
|
+
placeholder: "macOS 15.3"
|
|
47
|
+
validations:
|
|
48
|
+
required: true
|
|
49
|
+
- type: textarea
|
|
50
|
+
id: doctor
|
|
51
|
+
attributes:
|
|
52
|
+
label: "`noetrail doctor` output"
|
|
53
|
+
description: The report from the instance the proposal is about. It shows the schema version, the loaded packs, and the layout the request has to fit.
|
|
54
|
+
render: json
|
|
55
|
+
validations:
|
|
56
|
+
required: true
|
|
57
|
+
- type: textarea
|
|
58
|
+
id: problem
|
|
59
|
+
attributes:
|
|
60
|
+
label: Problem
|
|
61
|
+
description: What you are trying to do today, and where the current commands or MCP tools stop you. Describe the situation, not the solution.
|
|
62
|
+
validations:
|
|
63
|
+
required: true
|
|
64
|
+
- type: textarea
|
|
65
|
+
id: proposal
|
|
66
|
+
attributes:
|
|
67
|
+
label: Proposed change
|
|
68
|
+
description: The smallest change that would solve it. Name the affected surface — CLI, MCP, schema packs, on-disk format, documentation.
|
|
69
|
+
validations:
|
|
70
|
+
required: true
|
|
71
|
+
- type: textarea
|
|
72
|
+
id: alternatives
|
|
73
|
+
attributes:
|
|
74
|
+
label: Alternatives and impact
|
|
75
|
+
description: What you considered instead, and what this would cost — a data-format change, a migration, a new dependency, a wider agent permission. Say so if you do not know.
|
|
76
|
+
validations:
|
|
77
|
+
required: true
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
The four sections below are the four things CONTRIBUTING.md asks a pull
|
|
3
|
+
request to describe. Keep one coherent change per pull request.
|
|
4
|
+
Delete a section only if you replace it with a sentence saying why it does not
|
|
5
|
+
apply.
|
|
6
|
+
-->
|
|
7
|
+
|
|
8
|
+
## Summary
|
|
9
|
+
|
|
10
|
+
<!-- What changes, and why. One paragraph. -->
|
|
11
|
+
|
|
12
|
+
## User-visible behavior and compatibility
|
|
13
|
+
|
|
14
|
+
<!--
|
|
15
|
+
Which command, MCP tool, output field, or file layout changes, and what an
|
|
16
|
+
existing installation notices. Write "none" if nothing user-visible changes.
|
|
17
|
+
-->
|
|
18
|
+
|
|
19
|
+
## Security and privacy boundaries
|
|
20
|
+
|
|
21
|
+
<!--
|
|
22
|
+
Which boundary this touches: the Git/private-data separation, the narrow MCP
|
|
23
|
+
surface, the isolated bookmark fetcher, attachment ingestion, purge, secrets.
|
|
24
|
+
Write "none affected" if it touches none of them.
|
|
25
|
+
-->
|
|
26
|
+
|
|
27
|
+
## Tests run
|
|
28
|
+
|
|
29
|
+
<!--
|
|
30
|
+
Paste the commands you ran and their result. `make check` covers all six
|
|
31
|
+
gates; name the individual gates if you ran them separately.
|
|
32
|
+
-->
|
|
33
|
+
|
|
34
|
+
## Migration, rollback, and documentation
|
|
35
|
+
|
|
36
|
+
<!--
|
|
37
|
+
On-disk format changes need an ordered, deterministic, dry-run migration and a
|
|
38
|
+
rollback path. Name the documents you updated, or say why none needed it.
|
|
39
|
+
-->
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
- [ ] `make check` passes locally (lint, types, tests, coverage, secrets, boundary).
|
|
44
|
+
- [ ] Tests and fixtures use synthetic data only — no real vault, export, attachment, URL, or credential.
|
|
45
|
+
- [ ] Documentation, `CHANGELOG.md`, and any affected `docs/` page are updated.
|
|
46
|
+
- [ ] No generated wheels, private runtime directories, or copied logs are included.
|
|
47
|
+
- [ ] I am submitting this under the [Apache License 2.0](../LICENSE), per section 5 of that license.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
|
|
3
|
+
updates:
|
|
4
|
+
# The workflows pin actions to a commit SHA, which is safe but frozen:
|
|
5
|
+
# without this, a pinned action would keep running its original code
|
|
6
|
+
# indefinitely, security fixes included. Dependabot rewrites the SHA and the
|
|
7
|
+
# trailing version comment together.
|
|
8
|
+
- package-ecosystem: "github-actions"
|
|
9
|
+
directory: "/"
|
|
10
|
+
schedule:
|
|
11
|
+
interval: "weekly"
|
|
12
|
+
commit-message:
|
|
13
|
+
prefix: "ci"
|
|
14
|
+
labels:
|
|
15
|
+
- "dependencies"
|
|
16
|
+
- "github-actions"
|
|
17
|
+
|
|
18
|
+
# There is deliberately no "pip" entry: the runtime has no third-party
|
|
19
|
+
# dependencies, and the two CI-only tools are pinned in the workflows.
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
# An unfiltered `push` plus `pull_request` ran every job twice for any branch
|
|
4
|
+
# that had an open pull request. Pushes are now limited to the branch and the
|
|
5
|
+
# tags that are worth a run on their own; everything else arrives via the
|
|
6
|
+
# pull-request event.
|
|
7
|
+
on:
|
|
8
|
+
push:
|
|
9
|
+
branches: [main]
|
|
10
|
+
tags:
|
|
11
|
+
- "v[0-9]+.[0-9]+.[0-9]+"
|
|
12
|
+
- "v[0-9]+.[0-9]+.[0-9]+a[0-9]+"
|
|
13
|
+
- "v[0-9]+.[0-9]+.[0-9]+b[0-9]+"
|
|
14
|
+
- "v[0-9]+.[0-9]+.[0-9]+rc[0-9]+"
|
|
15
|
+
pull_request:
|
|
16
|
+
|
|
17
|
+
# Only the newest commit of a ref is interesting; superseded runs are cancelled
|
|
18
|
+
# instead of competing for runners.
|
|
19
|
+
concurrency:
|
|
20
|
+
group: ci-${{ github.ref }}
|
|
21
|
+
cancel-in-progress: true
|
|
22
|
+
|
|
23
|
+
permissions:
|
|
24
|
+
contents: read
|
|
25
|
+
|
|
26
|
+
# Third-party actions are pinned to a commit SHA. A mutable major tag can be
|
|
27
|
+
# repointed at new code without any change in this repository, so the version
|
|
28
|
+
# in the trailing comment is documentation only.
|
|
29
|
+
jobs:
|
|
30
|
+
lint:
|
|
31
|
+
name: Lint
|
|
32
|
+
runs-on: ubuntu-latest
|
|
33
|
+
timeout-minutes: 10
|
|
34
|
+
|
|
35
|
+
steps:
|
|
36
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
37
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
38
|
+
with:
|
|
39
|
+
python-version: "3.13"
|
|
40
|
+
- name: Install linter
|
|
41
|
+
run: python -m pip install ruff==0.14.0
|
|
42
|
+
- name: Check style and common defects
|
|
43
|
+
run: python -m ruff check .
|
|
44
|
+
|
|
45
|
+
typecheck:
|
|
46
|
+
name: Type check
|
|
47
|
+
runs-on: ubuntu-latest
|
|
48
|
+
timeout-minutes: 10
|
|
49
|
+
|
|
50
|
+
steps:
|
|
51
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
52
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
53
|
+
with:
|
|
54
|
+
# The lowest supported interpreter: mypy resolves version-conditional
|
|
55
|
+
# standard-library stubs against the running Python, so checking on
|
|
56
|
+
# 3.13 would not see what 3.11 users get.
|
|
57
|
+
python-version: "3.11"
|
|
58
|
+
- name: Install type checker
|
|
59
|
+
run: python -m pip install mypy==1.20.2
|
|
60
|
+
# Scope, strictness and per-module overrides live in pyproject.toml.
|
|
61
|
+
- name: Check types
|
|
62
|
+
run: python -m mypy
|
|
63
|
+
|
|
64
|
+
test:
|
|
65
|
+
name: Python ${{ matrix.python-version }} on ${{ matrix.os }}
|
|
66
|
+
runs-on: ${{ matrix.os }}
|
|
67
|
+
timeout-minutes: 15
|
|
68
|
+
strategy:
|
|
69
|
+
fail-fast: false
|
|
70
|
+
matrix:
|
|
71
|
+
os: [ubuntu-latest]
|
|
72
|
+
python-version: ["3.11", "3.12", "3.13", "3.14"]
|
|
73
|
+
# One macOS job, not a second full matrix. Its purpose is the platform,
|
|
74
|
+
# not the interpreter: `/var` is a symlink there and `/tmp` on Linux is
|
|
75
|
+
# not, which is a difference the suite has already been wrong about.
|
|
76
|
+
# A macOS runner also bills at ten times a Linux one on a private
|
|
77
|
+
# repository, so the coverage is bought at one job, on the version the
|
|
78
|
+
# other gates use.
|
|
79
|
+
include:
|
|
80
|
+
- os: macos-latest
|
|
81
|
+
python-version: "3.13"
|
|
82
|
+
|
|
83
|
+
steps:
|
|
84
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
85
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
86
|
+
with:
|
|
87
|
+
python-version: ${{ matrix.python-version }}
|
|
88
|
+
- name: Run synthetic tests
|
|
89
|
+
run: python -m unittest discover -s tests -t . -v
|
|
90
|
+
- name: Check repository for secrets
|
|
91
|
+
run: python tools/check_secrets.py
|
|
92
|
+
- name: Check Git and private-data boundary
|
|
93
|
+
run: python tools/check_git_boundary.py
|
|
94
|
+
- name: Build wheel
|
|
95
|
+
run: python -m pip wheel . --wheel-dir "${RUNNER_TEMP}/wheel"
|
|
96
|
+
|
|
97
|
+
coverage:
|
|
98
|
+
name: Coverage
|
|
99
|
+
runs-on: ubuntu-latest
|
|
100
|
+
timeout-minutes: 20
|
|
101
|
+
|
|
102
|
+
steps:
|
|
103
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
104
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
105
|
+
with:
|
|
106
|
+
python-version: "3.13"
|
|
107
|
+
# `tools/coverage.py` is dependency-free and traces the child processes
|
|
108
|
+
# the suite starts, which is most of it. Thresholds live in that file and
|
|
109
|
+
# a shortfall fails this job.
|
|
110
|
+
- name: Measure statement coverage
|
|
111
|
+
run: python tools/coverage.py --json "${RUNNER_TEMP}/coverage.json"
|
|
112
|
+
|
|
113
|
+
sdist:
|
|
114
|
+
name: Source-distribution acceptance
|
|
115
|
+
runs-on: ubuntu-latest
|
|
116
|
+
timeout-minutes: 20
|
|
117
|
+
|
|
118
|
+
steps:
|
|
119
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
120
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
121
|
+
with:
|
|
122
|
+
python-version: "3.13"
|
|
123
|
+
- name: Install build frontend
|
|
124
|
+
run: python -m pip install build==1.5.1
|
|
125
|
+
- name: Build source distribution
|
|
126
|
+
run: python -m build --sdist --outdir dist
|
|
127
|
+
# The sdist is the artifact a distribution packager rebuilds and tests
|
|
128
|
+
# from. Running the suite inside the unpacked archive is the only check
|
|
129
|
+
# that catches a file MANIFEST.in forgot -- `tests/__init__.py` was
|
|
130
|
+
# missing once, and nothing outside this job noticed.
|
|
131
|
+
- name: Run the suite from the unpacked source distribution
|
|
132
|
+
run: |
|
|
133
|
+
mkdir -p "${RUNNER_TEMP}/sdist"
|
|
134
|
+
tar xzf dist/noetrail-*.tar.gz -C "${RUNNER_TEMP}/sdist"
|
|
135
|
+
cd "${RUNNER_TEMP}/sdist"/noetrail-*/
|
|
136
|
+
python -m unittest discover -s tests -t . -v
|
|
137
|
+
|
|
138
|
+
installed-wheel:
|
|
139
|
+
name: Installed-wheel acceptance
|
|
140
|
+
runs-on: ubuntu-latest
|
|
141
|
+
timeout-minutes: 20
|
|
142
|
+
|
|
143
|
+
steps:
|
|
144
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
145
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
146
|
+
with:
|
|
147
|
+
python-version: "3.13"
|
|
148
|
+
- name: Build wheel
|
|
149
|
+
run: python -m pip wheel . --no-deps --wheel-dir dist
|
|
150
|
+
- name: Install and exercise the wheel
|
|
151
|
+
run: |
|
|
152
|
+
python tools/release_acceptance.py \
|
|
153
|
+
--wheel "$(find dist -name 'noetrail-*.whl' -print -quit)"
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
name: CodeQL
|
|
2
|
+
|
|
3
|
+
# Static analysis on the Python sources. Runs on the same events as CI plus a
|
|
4
|
+
# weekly schedule, because CodeQL queries are updated independently of this
|
|
5
|
+
# repository and a finding can appear without any commit here.
|
|
6
|
+
on:
|
|
7
|
+
push:
|
|
8
|
+
branches: [main]
|
|
9
|
+
pull_request:
|
|
10
|
+
branches: [main]
|
|
11
|
+
schedule:
|
|
12
|
+
- cron: "17 5 * * 1"
|
|
13
|
+
|
|
14
|
+
concurrency:
|
|
15
|
+
group: codeql-${{ github.ref }}
|
|
16
|
+
cancel-in-progress: true
|
|
17
|
+
|
|
18
|
+
permissions:
|
|
19
|
+
contents: read
|
|
20
|
+
|
|
21
|
+
# Third-party actions are pinned to a commit SHA. A mutable major tag can be
|
|
22
|
+
# repointed at new code without any change in this repository, so the version
|
|
23
|
+
# in the trailing comment is documentation only.
|
|
24
|
+
jobs:
|
|
25
|
+
analyze:
|
|
26
|
+
name: Analyze Python
|
|
27
|
+
runs-on: ubuntu-latest
|
|
28
|
+
timeout-minutes: 20
|
|
29
|
+
# Code scanning needs GitHub Advanced Security on a private repository; on
|
|
30
|
+
# a personal plan CodeQL is only free for public ones. Without it the job
|
|
31
|
+
# fails during init with a permissions error rather than a finding, which
|
|
32
|
+
# is noise on every pull request and would block a required check for a
|
|
33
|
+
# reason that has nothing to do with the code. Skipping while private
|
|
34
|
+
# keeps the workflow honest: it starts analysing by itself the moment the
|
|
35
|
+
# repository is published, with no change here.
|
|
36
|
+
if: github.event.repository.private == false
|
|
37
|
+
permissions:
|
|
38
|
+
# Writing the results into the repository's code-scanning view is the
|
|
39
|
+
# only extra permission this job needs.
|
|
40
|
+
security-events: write
|
|
41
|
+
|
|
42
|
+
steps:
|
|
43
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
44
|
+
- name: Initialize CodeQL
|
|
45
|
+
uses: github/codeql-action/init@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
|
|
46
|
+
with:
|
|
47
|
+
languages: python
|
|
48
|
+
build-mode: none
|
|
49
|
+
queries: security-and-quality
|
|
50
|
+
- name: Perform CodeQL analysis
|
|
51
|
+
uses: github/codeql-action/analyze@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
|
|
52
|
+
with:
|
|
53
|
+
category: "/language:python"
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
name: Publish ZeroClaw candidate
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_run:
|
|
5
|
+
workflows: [CI]
|
|
6
|
+
types: [completed]
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
concurrency:
|
|
13
|
+
group: zeroclaw-candidate
|
|
14
|
+
cancel-in-progress: false
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
candidate:
|
|
18
|
+
if: >-
|
|
19
|
+
github.event.workflow_run.conclusion == 'success' &&
|
|
20
|
+
github.event.workflow_run.event == 'push' &&
|
|
21
|
+
github.event.workflow_run.head_branch == 'main' &&
|
|
22
|
+
github.event.workflow_run.head_repository.full_name == github.repository
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
timeout-minutes: 5
|
|
25
|
+
permissions:
|
|
26
|
+
contents: write
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
29
|
+
with:
|
|
30
|
+
ref: ${{ github.event.workflow_run.head_sha }}
|
|
31
|
+
fetch-depth: 1
|
|
32
|
+
- name: Publish the tested main commit
|
|
33
|
+
env:
|
|
34
|
+
CANDIDATE_SHA: ${{ github.event.workflow_run.head_sha }}
|
|
35
|
+
run: |
|
|
36
|
+
set -euo pipefail
|
|
37
|
+
git fetch origin main
|
|
38
|
+
if [ "$(git rev-parse origin/main)" != "$CANDIDATE_SHA" ]; then
|
|
39
|
+
echo "A newer main commit exists; skip this candidate."
|
|
40
|
+
exit 0
|
|
41
|
+
fi
|
|
42
|
+
python3 tools/zeroclaw_candidate.py "$CANDIDATE_SHA" deploy/zeroclaw/candidate
|
|
43
|
+
git config user.name github-actions\[bot\]
|
|
44
|
+
git config user.email 41898282+github-actions\[bot\]@users.noreply.github.com
|
|
45
|
+
git add deploy/zeroclaw/candidate
|
|
46
|
+
git commit -m "ci: publish candidate $CANDIDATE_SHA"
|
|
47
|
+
# Only this generated branch is replaced; main remains PR-protected.
|
|
48
|
+
# Concurrency serializes publishers, and the main check rejects stale CI.
|
|
49
|
+
git push --force origin HEAD:refs/heads/deploy/test
|