assertion-cli 0.5.10__tar.gz → 0.5.12__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 (32) hide show
  1. {assertion_cli-0.5.10 → assertion_cli-0.5.12}/PKG-INFO +1 -1
  2. {assertion_cli-0.5.10 → assertion_cli-0.5.12}/assertion_cli.egg-info/PKG-INFO +1 -1
  3. {assertion_cli-0.5.10 → assertion_cli-0.5.12}/main.py +12 -11
  4. {assertion_cli-0.5.10 → assertion_cli-0.5.12}/pyproject.toml +1 -1
  5. assertion_cli-0.5.12/templates/AGENTS.md +26 -0
  6. {assertion_cli-0.5.10 → assertion_cli-0.5.12}/templates/SKILL.md +1 -1
  7. {assertion_cli-0.5.10 → assertion_cli-0.5.12}/tests/test_git.py +0 -1
  8. {assertion_cli-0.5.10 → assertion_cli-0.5.12}/tests/test_new.py +6 -3
  9. {assertion_cli-0.5.10 → assertion_cli-0.5.12}/tests/test_session_start.py +11 -7
  10. assertion_cli-0.5.10/templates/AGENTS.md +0 -14
  11. {assertion_cli-0.5.10 → assertion_cli-0.5.12}/README.md +0 -0
  12. {assertion_cli-0.5.10 → assertion_cli-0.5.12}/api.py +0 -0
  13. {assertion_cli-0.5.10 → assertion_cli-0.5.12}/assertion_cli.egg-info/SOURCES.txt +0 -0
  14. {assertion_cli-0.5.10 → assertion_cli-0.5.12}/assertion_cli.egg-info/dependency_links.txt +0 -0
  15. {assertion_cli-0.5.10 → assertion_cli-0.5.12}/assertion_cli.egg-info/entry_points.txt +0 -0
  16. {assertion_cli-0.5.10 → assertion_cli-0.5.12}/assertion_cli.egg-info/requires.txt +0 -0
  17. {assertion_cli-0.5.10 → assertion_cli-0.5.12}/assertion_cli.egg-info/top_level.txt +0 -0
  18. {assertion_cli-0.5.10 → assertion_cli-0.5.12}/bundle.py +0 -0
  19. {assertion_cli-0.5.10 → assertion_cli-0.5.12}/git.py +0 -0
  20. {assertion_cli-0.5.10 → assertion_cli-0.5.12}/link.py +0 -0
  21. {assertion_cli-0.5.10 → assertion_cli-0.5.12}/models.py +0 -0
  22. {assertion_cli-0.5.10 → assertion_cli-0.5.12}/session.py +0 -0
  23. {assertion_cli-0.5.10 → assertion_cli-0.5.12}/setup.cfg +0 -0
  24. {assertion_cli-0.5.10 → assertion_cli-0.5.12}/templates/__init__.py +0 -0
  25. {assertion_cli-0.5.10 → assertion_cli-0.5.12}/tests/test_api.py +0 -0
  26. {assertion_cli-0.5.10 → assertion_cli-0.5.12}/tests/test_bundle.py +0 -0
  27. {assertion_cli-0.5.10 → assertion_cli-0.5.12}/tests/test_decision.py +0 -0
  28. {assertion_cli-0.5.10 → assertion_cli-0.5.12}/tests/test_install.py +0 -0
  29. {assertion_cli-0.5.10 → assertion_cli-0.5.12}/tests/test_link.py +0 -0
  30. {assertion_cli-0.5.10 → assertion_cli-0.5.12}/tests/test_main.py +0 -0
  31. {assertion_cli-0.5.10 → assertion_cli-0.5.12}/tests/test_prompt.py +0 -0
  32. {assertion_cli-0.5.10 → assertion_cli-0.5.12}/tests/test_session.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: assertion-cli
3
- Version: 0.5.10
3
+ Version: 0.5.12
4
4
  Summary: CLI for the Assertion API
5
5
  Requires-Python: >=3.13
6
6
  Description-Content-Type: text/markdown
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: assertion-cli
3
- Version: 0.5.10
3
+ Version: 0.5.12
4
4
  Summary: CLI for the Assertion API
5
5
  Requires-Python: >=3.13
6
6
  Description-Content-Type: text/markdown
@@ -16,6 +16,7 @@ from git import (
16
16
  find_git_root,
17
17
  get_full_diff,
18
18
  get_head_branch,
19
+ get_head_sha,
19
20
  get_merge_base,
20
21
  get_uncommitted_diff,
21
22
  get_upstream_ref,
@@ -271,8 +272,9 @@ def _resolve_diff_base(repo_root: Path) -> str:
271
272
  refs (from a force-pushed or rebased branch) would otherwise produce a
272
273
  merge-base that's no longer reachable from any remote ref.
273
274
 
274
- Errors out when no upstream can be resolved (detached HEAD, no tracking
275
- branch, branch not pushed to remote).
275
+ Falls back to HEAD when no upstream can be resolved (e.g. Codex cloud
276
+ sandboxes with no remote tracking refs) — the branch was cloned from the
277
+ remote so HEAD exists on the remote at session start time.
276
278
  """
277
279
  try:
278
280
  run_git_command(repo_root, ["fetch", "--no-tags", "origin"])
@@ -281,13 +283,11 @@ def _resolve_diff_base(repo_root: Path) -> str:
281
283
 
282
284
  upstream = get_upstream_ref(repo_root)
283
285
  if upstream is None:
284
- exit_with_error(
285
- "Cannot determine the diff base: no upstream tracking branch found.\n"
286
- "Make sure you are on a branch that has been pushed to a remote "
287
- "with a tracking branch configured, e.g.:\n"
288
- " git push -u origin <branch>\n"
289
- "Or use an existing branch that tracks an upstream.",
286
+ typer.echo(
287
+ "Warning: no upstream tracking branch found, falling back to HEAD.",
288
+ err=True,
290
289
  )
290
+ return get_head_sha(repo_root)
291
291
  return get_merge_base(repo_root, upstream)
292
292
 
293
293
 
@@ -296,9 +296,10 @@ def session_start() -> None:
296
296
  """Record the merge-base with the upstream tracking branch as the diff base.
297
297
 
298
298
  Unlike the old HEAD-based approach, the merge-base always exists on the
299
- remote so the backend can check it out. Branches without a remote tracking
300
- ref (detached HEAD, no upstream, not pushed) are rejected with a clear
301
- message run ``asrt session start`` from a branch with an upstream.
299
+ remote so the backend can check it out. When no upstream tracking branch
300
+ can be resolved (e.g. Codex cloud sandboxes), falls back to HEAD the
301
+ branch was cloned from the remote so HEAD exists on the remote at session
302
+ start time.
302
303
 
303
304
  `session start` does not write skill files — that is `asrt install`, the
304
305
  one-time onboarding step. It also never touches user content in `CLAUDE.md` /
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "assertion-cli"
7
- version = "0.5.10"
7
+ version = "0.5.12"
8
8
  description = "CLI for the Assertion API"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.13"
@@ -0,0 +1,26 @@
1
+ # Assertion verification
2
+
3
+ This repo uses the Assertion CLI (`asrt`) to track user intent and verify your work. The full workflow lives in the `assertion-cli` skill:
4
+
5
+ - **Claude Code** — [`.claude/skills/assertion-cli/SKILL.md`](.claude/skills/assertion-cli/SKILL.md)
6
+ - **Codex / Cursor** — [`.agents/skills/assertion-cli/SKILL.md`](.agents/skills/assertion-cli/SKILL.md)
7
+
8
+ Both files are byte-identical — read whichever your agent loads (or either one directly). In brief, follow these three rules for every conversation:
9
+
10
+ 1. **Every user message:** call `asrt prompt "<exact text of the message>"` before doing any other work for that turn. Apply to every user turn, not just the first.
11
+ 2. **Checkpoint at trajectory-feedback moments** with `asrt checkpoint` — a handful across a feature build, not one per file.
12
+ 3. **Verify, then PR with the session marker.** At completion, run `asrt verify` and poll `asrt verify-status` until clean. Then open the PR and embed the hidden session marker — `$(asrt get-link)`, an HTML comment — in its body.
13
+
14
+ **The session marker is mandatory, not optional.** It's an HTML comment carrying the session URL — `asrt get-link` prints exactly this form:
15
+
16
+ ```
17
+ <!-- assertion-session: https://app.tryassertion.com/sessions/<id> -->
18
+ ```
19
+
20
+ Every PR opened from an Assertion session **must** carry it: the Assertion GitHub bot links the PR to the verification session by branch name first, and falls back to this marker when the branch doesn't match — without it, that PR can't be linked. So:
21
+
22
+ - Put `$(asrt get-link)` in the PR body via `gh pr create`/`gh pr edit` — never paste the bare URL into the visible description.
23
+ - After creating or editing the PR, **confirm the marker actually landed in the raw body** (`gh pr view --json body --jq .body | grep -q 'assertion-session:'`). It won't show in the rendered description — that's expected.
24
+ - A missing marker is a **blocking error, not a warning**: do not consider the task done, and do not open a PR at all, until the marker is verified present. Re-run `gh pr edit` with `$(asrt get-link)` and re-check until it passes.
25
+
26
+ See the skill file for the full rules, edge cases, and the exact PR command (section: *Embed the hidden session marker in the PR*).
@@ -15,7 +15,7 @@ Before any `asrt` call:
15
15
 
16
16
  - You are inside a git repository.
17
17
  - `asrt install` has been run once in this repo. It installs the skill files you are reading right now (plus the `AGENTS.md` / `CLAUDE.md` pointer and `.gitignore` rules). This is an onboarding step, not a per-run one.
18
- - `asrt session start` has been run for this work session. It records the current HEAD as the diff base that every checkpoint/verify diffs against. If `asrt checkpoint` or `asrt verify` errors with "No diff base recorded", run `asrt session start` and retry.
18
+ - `asrt session start` has been run for this work session. It records the merge-base with the upstream tracking branch (falling back to HEAD when no upstream is available) as the diff base that every checkpoint/verify diffs against. If `asrt checkpoint` or `asrt verify` errors with "No diff base recorded", run `asrt session start` and retry.
19
19
 
20
20
  **First command sequence for a new work session:**
21
21
 
@@ -7,7 +7,6 @@ from click.exceptions import Exit as ClickExit
7
7
  from git import (
8
8
  find_git_root,
9
9
  get_full_diff,
10
- get_head_branch,
11
10
  get_head_sha,
12
11
  get_merge_base,
13
12
  get_uncommitted_diff,
@@ -125,15 +125,18 @@ def test_new_leaves_next_checkpoint_requiring_stack(
125
125
  assert not (assertion_dir / "metadata.json").exists()
126
126
 
127
127
 
128
- def test_new_requires_upstream_tracking_branch(
128
+ def test_new_falls_back_to_head_when_no_upstream(
129
129
  tmp_path: Path,
130
130
  monkeypatch,
131
131
  ) -> None:
132
+ """When no upstream tracking branch exists, fall back to HEAD instead of erroring."""
132
133
  _run_git(tmp_path, "init")
133
134
  _run_git(tmp_path, "commit", "--allow-empty", "-m", "init")
135
+ head_sha = _run_git(tmp_path, "rev-parse", "HEAD")
134
136
  monkeypatch.chdir(tmp_path)
135
137
 
136
138
  result = runner.invoke(main.app, ["new"])
137
139
 
138
- assert result.exit_code == 1
139
- assert "no upstream tracking branch" in result.stderr
140
+ assert result.exit_code == 0
141
+ assert "falling back to HEAD" in result.stderr
142
+ assert (tmp_path / ".assertion" / "base_sha").read_text().strip() == head_sha
@@ -197,23 +197,27 @@ def test_session_start_requires_git_repo(tmp_path: Path, monkeypatch) -> None:
197
197
  assert "git repository" in result.stderr
198
198
 
199
199
 
200
- def test_session_start_requires_upstream_tracking_branch(
200
+ def test_session_start_falls_back_to_head_when_no_upstream(
201
201
  tmp_path: Path, monkeypatch
202
202
  ) -> None:
203
+ """When no upstream tracking branch exists, fall back to HEAD instead of erroring.
204
+
205
+ Codex cloud sandboxes may not have upstream tracking configured, but the
206
+ branch was cloned from the remote so HEAD exists on the remote.
207
+ """
203
208
  _run_git(tmp_path, "init")
204
209
  _run_git(tmp_path, "commit", "--allow-empty", "-m", "init")
210
+ head_sha = _run_git(tmp_path, "rev-parse", "HEAD")
205
211
  monkeypatch.chdir(tmp_path)
206
212
 
207
213
  result = runner.invoke(main.app, ["session", "start"])
208
214
 
209
- assert result.exit_code == 1
210
- assert "no upstream tracking branch" in result.stderr
211
- assert not (tmp_path / ".assertion" / "base_sha").exists()
215
+ assert result.exit_code == 0
216
+ assert "falling back to HEAD" in result.stderr
217
+ assert (tmp_path / ".assertion" / "base_sha").read_text().strip() == head_sha
212
218
 
213
219
 
214
- def test_session_start_records_merge_base_as_base(
215
- tmp_path: Path, monkeypatch
216
- ) -> None:
220
+ def test_session_start_records_merge_base_as_base(tmp_path: Path, monkeypatch) -> None:
217
221
  """`asrt session start` pins the diff base to the branch merge-base.
218
222
 
219
223
  Every subsequent checkpoint/verify diffs against this SHA, so backend can
@@ -1,14 +0,0 @@
1
- # Assertion verification
2
-
3
- This repo uses the Assertion CLI (`asrt`) to track user intent and verify your work. The full workflow lives in the `assertion-cli` skill:
4
-
5
- - **Claude Code** — [`.claude/skills/assertion-cli/SKILL.md`](.claude/skills/assertion-cli/SKILL.md)
6
- - **Codex / Cursor** — [`.agents/skills/assertion-cli/SKILL.md`](.agents/skills/assertion-cli/SKILL.md)
7
-
8
- Both files are byte-identical — read whichever your agent loads (or either one directly). In brief, follow these three rules for every conversation:
9
-
10
- 1. **Every user message:** call `asrt prompt "<exact text of the message>"` before doing any other work for that turn. Apply to every user turn, not just the first.
11
- 2. **Checkpoint at trajectory-feedback moments** with `asrt checkpoint` — a handful across a feature build, not one per file.
12
- 3. **Verify at completion** with `asrt verify`. Once it is clean, open a PR whose body embeds the hidden session marker from `asrt get-link`.
13
-
14
- See the skill file for the full rules, edge cases, and the exact PR command.
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes