napkinstack 0.6.0__tar.gz → 0.6.1__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.
- {napkinstack-0.6.0 → napkinstack-0.6.1}/PKG-INFO +12 -10
- {napkinstack-0.6.0 → napkinstack-0.6.1}/README.md +11 -9
- {napkinstack-0.6.0 → napkinstack-0.6.1}/pyproject.toml +1 -1
- {napkinstack-0.6.0 → napkinstack-0.6.1}/pyproject.toml.orig +1 -1
- {napkinstack-0.6.0 → napkinstack-0.6.1}/src/napkinstack/project.py +19 -7
- {napkinstack-0.6.0 → napkinstack-0.6.1}/LICENSE +0 -0
- {napkinstack-0.6.0 → napkinstack-0.6.1}/src/napkinstack/__init__.py +0 -0
- {napkinstack-0.6.0 → napkinstack-0.6.1}/src/napkinstack/cli.py +0 -0
- {napkinstack-0.6.0 → napkinstack-0.6.1}/src/napkinstack/compat.py +0 -0
- {napkinstack-0.6.0 → napkinstack-0.6.1}/src/napkinstack/discovery.py +0 -0
- {napkinstack-0.6.0 → napkinstack-0.6.1}/src/napkinstack/doctor.py +0 -0
- {napkinstack-0.6.0 → napkinstack-0.6.1}/src/napkinstack/fitness/__init__.py +0 -0
- {napkinstack-0.6.0 → napkinstack-0.6.1}/src/napkinstack/fitness/boundaries.py +0 -0
- {napkinstack-0.6.0 → napkinstack-0.6.1}/src/napkinstack/fitness/hygiene.py +0 -0
- {napkinstack-0.6.0 → napkinstack-0.6.1}/src/napkinstack/fitness/manifests.py +0 -0
- {napkinstack-0.6.0 → napkinstack-0.6.1}/src/napkinstack/fitness/plan.py +0 -0
- {napkinstack-0.6.0 → napkinstack-0.6.1}/src/napkinstack/fitness/pr_scope.py +0 -0
- {napkinstack-0.6.0 → napkinstack-0.6.1}/src/napkinstack/landed.py +0 -0
- {napkinstack-0.6.0 → napkinstack-0.6.1}/src/napkinstack/modules.py +0 -0
- {napkinstack-0.6.0 → napkinstack-0.6.1}/src/napkinstack/provenance.py +0 -0
- {napkinstack-0.6.0 → napkinstack-0.6.1}/src/napkinstack/pull_request.py +0 -0
- {napkinstack-0.6.0 → napkinstack-0.6.1}/src/napkinstack/skills.py +0 -0
- {napkinstack-0.6.0 → napkinstack-0.6.1}/src/napkinstack/templates/module/AGENTS.md +0 -0
- {napkinstack-0.6.0 → napkinstack-0.6.1}/src/napkinstack/templates/module/MANIFEST.yaml +0 -0
- {napkinstack-0.6.0 → napkinstack-0.6.1}/src/napkinstack/templates/module/README.md +0 -0
- {napkinstack-0.6.0 → napkinstack-0.6.1}/src/napkinstack/templates/module/docs/adr/.gitkeep +0 -0
- {napkinstack-0.6.0 → napkinstack-0.6.1}/src/napkinstack/templates/module/src/.gitkeep +0 -0
- {napkinstack-0.6.0 → napkinstack-0.6.1}/src/napkinstack/templates/module/tests/.gitkeep +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: napkinstack
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.1
|
|
4
4
|
Summary: Engineering framework for several teams and their agents working in one repository: modules, contracts, guardrails in CI.
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -20,21 +20,23 @@ modules, contracts, guardrails in CI. On the Django or Rails model, one command
|
|
|
20
20
|
the project, which then receives new versions on demand; no application stack is imposed.
|
|
21
21
|
Positioning and vocabulary: [`PRODUCT.md`](PRODUCT.md) §1.
|
|
22
22
|
|
|
23
|
-
> **Status: v0.
|
|
24
|
-
>
|
|
25
|
-
> module uses, a contract version someone relies on changes only with a proof
|
|
26
|
-
> checks and stale approvals are enforced, a verifier is not
|
|
27
|
-
> the framework that gave it.
|
|
28
|
-
>
|
|
29
|
-
>
|
|
30
|
-
>
|
|
31
|
-
>
|
|
23
|
+
> **Status: v0.6.0, published** ([PyPI](https://pypi.org/project/napkinstack/)): what the
|
|
24
|
+
> framework announces, it refuses — and what it cannot refuse, it says. The boundaries read the
|
|
25
|
+
> contracts a module uses, a contract version someone relies on changes only with a proof that
|
|
26
|
+
> runs in the base's tree, the module checks and stale approvals are enforced, a verifier is not
|
|
27
|
+
> an author, and every verdict names the framework that gave it. Since v0.6.0, a document still
|
|
28
|
+
> holding its template's words is refused, a deprecated module's consumers are named with their
|
|
29
|
+
> removal date, and a contract change runs the checks of both sides — the producer and every
|
|
30
|
+
> declared consumer. The diagnosis says whether anything refuses at all; a record names what
|
|
31
|
+
> reached the default branch outside a pull request, and never refuses it. A first pilot
|
|
32
|
+
> project, private, starts from here.
|
|
32
33
|
> Tracking: [engine roadmap](docs/governance/plans/2026-09-15-engine-v0.1.0.md),
|
|
33
34
|
> [move to English](docs/governance/plans/2026-09-16-english-migration.md),
|
|
34
35
|
> [frame, verify, approve](docs/governance/plans/2026-09-16-v0.3.0-frame-verify-approve.md),
|
|
35
36
|
> [every barrier refuses](docs/governance/plans/2026-09-19-v0.4.0-every-barrier-refuses.md),
|
|
36
37
|
> [a proof that cannot be rewritten](docs/governance/plans/2026-09-20-v0.5.0-a-proof-that-cannot-be-rewritten.md),
|
|
37
38
|
> [the conformance suite](docs/governance/plans/2026-09-20-m12-conformance-suite.md),
|
|
39
|
+
> [what is announced refuses](docs/governance/plans/2026-09-20-v0.6.0-what-is-announced-refuses.md),
|
|
38
40
|
> [`docs/governance/workstreams.md`](docs/governance/workstreams.md).
|
|
39
41
|
|
|
40
42
|
## A project's journey
|
|
@@ -5,21 +5,23 @@ modules, contracts, guardrails in CI. On the Django or Rails model, one command
|
|
|
5
5
|
the project, which then receives new versions on demand; no application stack is imposed.
|
|
6
6
|
Positioning and vocabulary: [`PRODUCT.md`](PRODUCT.md) §1.
|
|
7
7
|
|
|
8
|
-
> **Status: v0.
|
|
9
|
-
>
|
|
10
|
-
> module uses, a contract version someone relies on changes only with a proof
|
|
11
|
-
> checks and stale approvals are enforced, a verifier is not
|
|
12
|
-
> the framework that gave it.
|
|
13
|
-
>
|
|
14
|
-
>
|
|
15
|
-
>
|
|
16
|
-
>
|
|
8
|
+
> **Status: v0.6.0, published** ([PyPI](https://pypi.org/project/napkinstack/)): what the
|
|
9
|
+
> framework announces, it refuses — and what it cannot refuse, it says. The boundaries read the
|
|
10
|
+
> contracts a module uses, a contract version someone relies on changes only with a proof that
|
|
11
|
+
> runs in the base's tree, the module checks and stale approvals are enforced, a verifier is not
|
|
12
|
+
> an author, and every verdict names the framework that gave it. Since v0.6.0, a document still
|
|
13
|
+
> holding its template's words is refused, a deprecated module's consumers are named with their
|
|
14
|
+
> removal date, and a contract change runs the checks of both sides — the producer and every
|
|
15
|
+
> declared consumer. The diagnosis says whether anything refuses at all; a record names what
|
|
16
|
+
> reached the default branch outside a pull request, and never refuses it. A first pilot
|
|
17
|
+
> project, private, starts from here.
|
|
17
18
|
> Tracking: [engine roadmap](docs/governance/plans/2026-09-15-engine-v0.1.0.md),
|
|
18
19
|
> [move to English](docs/governance/plans/2026-09-16-english-migration.md),
|
|
19
20
|
> [frame, verify, approve](docs/governance/plans/2026-09-16-v0.3.0-frame-verify-approve.md),
|
|
20
21
|
> [every barrier refuses](docs/governance/plans/2026-09-19-v0.4.0-every-barrier-refuses.md),
|
|
21
22
|
> [a proof that cannot be rewritten](docs/governance/plans/2026-09-20-v0.5.0-a-proof-that-cannot-be-rewritten.md),
|
|
22
23
|
> [the conformance suite](docs/governance/plans/2026-09-20-m12-conformance-suite.md),
|
|
24
|
+
> [what is announced refuses](docs/governance/plans/2026-09-20-v0.6.0-what-is-announced-refuses.md),
|
|
23
25
|
> [`docs/governance/workstreams.md`](docs/governance/workstreams.md).
|
|
24
26
|
|
|
25
27
|
## A project's journey
|
|
@@ -72,10 +72,13 @@ def _explain(exc: Exception, command: str, where: Path, source: str, ref: str) -
|
|
|
72
72
|
# git writes the cause on an `error:` line and the outcome on a `fatal:` one; keeping
|
|
73
73
|
# the last line alone drops the only one that says what happened (D54).
|
|
74
74
|
detail = " — ".join(line for line in lines if line.startswith(("error:", "fatal:"))) or lines[-1]
|
|
75
|
-
# A git `error:` line means git refused something local,
|
|
76
|
-
#
|
|
77
|
-
|
|
78
|
-
|
|
75
|
+
# A git `error:` line means git refused something local, and git has already named it:
|
|
76
|
+
# a file of the template's uncommitted state, which Copier copies into its clone, or
|
|
77
|
+
# anything else it could not open. The action points at that line rather than guessing
|
|
78
|
+
# which of the two it was (D55).
|
|
79
|
+
local = ("git named what it could not handle above: fix that file, or, when the "
|
|
80
|
+
"template's working tree is uncommitted, commit or stash it — Copier copies it "
|
|
81
|
+
"as it is.")
|
|
79
82
|
remote = "check --source and --ref (a vX.Y.Z tag), and network access."
|
|
80
83
|
return (f"FAIL [{command}] Template {source} at version {ref} unreachable: {detail}\n"
|
|
81
84
|
+ action + (local if detail.startswith("error:") else remote))
|
|
@@ -89,9 +92,18 @@ def init(destination: Path, answers: dict[str, str | None], source: str, ref: st
|
|
|
89
92
|
from napkinstack.doctor import CHECKLIST
|
|
90
93
|
|
|
91
94
|
destination = destination.resolve()
|
|
92
|
-
if destination.exists() and
|
|
93
|
-
print(f"FAIL [init] {destination} is not
|
|
94
|
-
" Action: pick a folder that is missing or empty.")
|
|
95
|
+
if destination.exists() and not destination.is_dir():
|
|
96
|
+
print(f"FAIL [init] {destination} is a file, not a folder: nstack init creates a new "
|
|
97
|
+
"project.\n Action: pick a folder that is missing or empty.")
|
|
98
|
+
return 1
|
|
99
|
+
# Naming what fills the folder: it is usually hidden — an editor's, an agent's — and a
|
|
100
|
+
# reader told only "not empty" goes hunting for it (D56).
|
|
101
|
+
entries = sorted(entry.name for entry in destination.iterdir()) if destination.exists() else []
|
|
102
|
+
if entries:
|
|
103
|
+
listed = ", ".join(entries[:4]) + (f", and {len(entries) - 4} more" if len(entries) > 4 else "")
|
|
104
|
+
print(f"FAIL [init] {destination} is not empty: it holds {listed}.\n"
|
|
105
|
+
" Action: pick a folder that is missing or empty, or create the project in a "
|
|
106
|
+
f"folder inside it — nstack init {destination}/<project>.")
|
|
95
107
|
return 1
|
|
96
108
|
data = {question: value for question, value in answers.items() if value is not None}
|
|
97
109
|
try:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|