Skip to content

Fixed task layout, PR bodies hold the details, a deliverables setting; release 0.4.0 - #14

Merged
Marius1311 merged 10 commits into
mainfrom
docs/deliverables
Oct 15, 2026
Merged

Marius1311 merged 10 commits into
mainfrom
docs/deliverables

Conversation

@Marius1311

@Marius1311 Marius1311 commented Oct 15, 2026 •

Copy link
Copy Markdown
Member

Every task had to write a findings report next to its README. Across the recent finished tasks of one analysis repo, the human never referred to a report: figures and their legends were what got read. Fewer than half the tasks had a report. README and report repeated each other, and when they disagreed it was a stale file name, a status or a "still holds" claim, in whichever copy nobody touched after the change.

  • Deliverables: agreed at the start, from the new deliverables setting (default "a figure"), which the session start lists. A task can change it, and the answer goes in the README. No report by default.
  • One owner per fact:
    • The PR body holds a PR's details (method, decisions with who took each and why, findings, what needs the human), laid out by the analysis template's PR template (Task PR template; the review guide checks what hooks can't analysis_template#22). It is final once merged.
    • The task README is the overview: deliverables, inputs, write-back, running, a jobs table, and a short summary of every PR and issue the session opened.
    • Findings live in the deliverables.
  • Fixed layout, enforced: a new hook holds the top level of a task directory and its README's headings to the task template, reading both from the template and paths.py. _common.py moves into scripts/, where the template's own run commands already needed it. Scripts are NN_<step>.py in run order.
  • Forward only: earlier task directories are never edited, fixed or updated; a new version names the one it follows.
  • Separation: figure rules, the GPU rule (to the template's AGENTS.md) and the storage-snapshot note (a compute-environment fact) leave the plugin. Jobs are counted with the compute environment's tools, so no cluster plugin is required. Commands and snippets the analysis template owns are linked, not copied. The skill no longer restates the session-start rules.

🤖 Generated with Claude Code

https://claude.ai/code/session_011aQpF4MA9v7dTVK1FqMMVJ

…e 0.4.0

No report by default: the agent asks what the task should deliver and records it.
Decisions, PRs and issues go in the README; deliverables and PR bodies link to it.
Earlier task directories are never edited. Figure naming is left to sci-figures.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011aQpF4MA9v7dTVK1FqMMVJ
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-15T09:27:30.889184Z 63fbac3 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9471359652

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread skills/analysis-workflow/SKILL.md Outdated
record the path.
4. `analysis-workflow check layout`, then push.
5. The worktree is removed only once no batch job submitted from it is still queued or running.
5. Open the PR and add it to the README. Its body links the task README and says what this PR adds or changes, by

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Push the README update after opening the PR

When creating the final PR, its number or URL is only available after step 4 has already pushed the branch. Adding that PR to the tracked README therefore creates a new local change, but the checklist never commits or pushes it, so following these steps leaves the PR without the required self-record. Explicitly commit and push the README update after PR creation.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 3c06a01: step 5 now opens the PR, adds it to the README and pushes again.

Marius1311 and others added 2 commits October 15, 2026 09:42
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011aQpF4MA9v7dTVK1FqMMVJ
A hook holds task directories and READMEs to the task template, read from the template itself. The PR
body, laid out by the analysis template's PR template, holds a PR's details; the README summarizes each
PR and lists the session's jobs. Analysis moves forward: earlier task directories are never edited.
`deliverables` sets the default a task proposes. Figure and compute-environment rules leave the plugin,
and what the analysis template owns is linked, not restated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011aQpF4MA9v7dTVK1FqMMVJ
@Marius1311 Marius1311 changed the title Ask for the deliverables; the README is the task's one record; release 0.4.0 Fixed task layout, PR bodies hold the details, a deliverables setting; release 0.4.0 Oct 15, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e5da9ec7e4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

**Run**
- Every output path comes from `PATHS = task_paths(__file__)` in `_common.py`; `PATHS.ensure()` in the writer.
A bare relative path written from a worktree dies with the worktree.
- `PATHS = task_paths(__file__)` lives in `scripts/_common.py`; call `PATHS.ensure()` in the writer.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Import _common from its new scripts location

When a user follows the template's Running commands from the task directory, the python -c "from _common ..." command searches the task root, but this change moves _common.py into scripts/; consequently the documented LOGS=... command raises ModuleNotFoundError. Update the command to import scripts._common or otherwise put scripts/ on the import path.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in eed76ee: the template's Running section now runs from scripts/, where _common.py lives, so both the step and the -c import resolve it.

Comment thread hooks/guard_task_layout.py Outdated
Comment on lines +73 to +75
allowed = {p.name for p in TEMPLATE.iterdir()} | output_dirs()
if top not in allowed:
return f"`{top}` is not part of a task directory, whose top holds only {', '.join(sorted(allowed))}."

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Allow documented task-local manifests

When a benchmark uses the task-local workspace supported by guard_worktree_pixi.py and documented under Environments, writing analysis/.../bench_v1/pixi.toml is rejected because the allowed top-level names omit the manifest. This makes ordinary Write/Edit operations unable to create or maintain the supported workspace; include the task-local manifest files in the permitted layout.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in eed76ee: pixi.toml and pixi.lock are allowed at a task's top level, for the task-local environment the skill describes; covered by a test.

Comment thread hooks/guard_task_layout.py Outdated
Comment on lines +62 to +66
for parent in path.parents:
if parent.name == "analysis":
return None
if TASK_DIR.match(parent.name):
return parent

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Stop task detection before nested versioned folders

If a valid task contains a nested directory whose artifact or package name ends in _vN, such as demo_v1/outputs/model_v1/config.json, this nearest-ancestor search treats model_v1 as a new task and rejects config.json as an invalid top-level entry. Since descendants of allowed directories are otherwise unrestricted, identify the actual task boundary rather than selecting a version-looking directory inside it.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in eed76ee: the task is the outermost _vN directory under analysis/, so demo_v1/outputs/model_v1/config.json belongs to demo_v1; covered by a test.

…ts outermost _vN

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011aQpF4MA9v7dTVK1FqMMVJ

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: eed76eeaff

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread hooks/guard_task_layout.py Outdated
Comment on lines +68 to +70
for i, parent in enumerate(parents):
if parent.name == "analysis":
return next((p for p in reversed(parents[:i]) if TASK_DIR.match(p.name)), None)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Anchor task discovery to the checkout's analysis directory

When an adopted repository is cloned beneath any directory literally named analysis (for example, /work/analysis/repo), editing a non-task path such as src/package_v1/config.json finds that external ancestor, treats package_v1 as a task, and blocks the valid edit for having an unknown top-level file. Resolve the checkout first and only search beneath <checkout>/analysis so unrelated ancestor names cannot activate the guard.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in da5faa0: the guard resolves the checkout first and looks for a task only below its own analysis/; covered by a test with the repo inside an unrelated analysis directory.

Marius1311 and others added 2 commits October 15, 2026 10:59
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011aQpF4MA9v7dTVK1FqMMVJ
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011aQpF4MA9v7dTVK1FqMMVJ

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0d224f78e7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread hooks/guard_task_layout.py Outdated
return found


def after(tool_input: dict, path: Path) -> str | None:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restore Python 3.9 compatibility in the layout hook

When the python3 on PATH is Python 3.9, evaluating this str | None annotation (and the later Path | None) raises TypeError while importing the hook, before main() can run; this is a supported hook runtime and causes every Write/Edit invocation to skip the new layout enforcement. Adding postponed annotations here is also insufficient by itself because output_dirs() executes the Python-3.12-targeted paths.py, which contains the same union syntax, so keep all code executed by this standalone hook Python-3.9-compatible.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 2f0dc48: postponed annotations, and the hook now reads the output directories from paths.py with ast instead of running it. Checked by running every hook, and an end-to-end task in a rendered project, under Python 3.9.

…d not run

Jobs table says completed, as Slurm and euler-jobs --summary do.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011aQpF4MA9v7dTVK1FqMMVJ

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2f0dc4876a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread hooks/guard_task_layout.py Outdated
if not path.is_relative_to(analysis):
return None
below = path.relative_to(analysis).parts[:-1]
return next((analysis.joinpath(*below[: i + 1]) for i, p in enumerate(below) if TASK_DIR.match(p)), None)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Do not treat versioned topic names as tasks

After the outermost-directory fix, a topic whose legitimate name ends in _vN is now mistaken for the task itself. For example, writing analysis/cohort_v1/demo_v1/scripts/01_step.py selects cohort_v1, then rejects demo_v1 as an invalid top-level entry; even a human notebook directly under analysis/cohort_v1/ is blocked. The documented <topic> component has no naming restriction, so task discovery needs to distinguish the actual task directory rather than reserving every version-looking ancestor.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in a06f447: walking down from analysis/, the task is the last _vN directory before the path enters a task's own entries, so cohort_v1/demo_v1/scripts/… belongs to demo_v1 and demo_v1/outputs/model_v1/… still to demo_v1; both tested. A file directly in a versioned topic can't be told from a task's own file; topics named <name>_vN collide with the task naming convention, so that case stays as is.

Comment thread hooks/hooks.json
Comment on lines +35 to +37
"type": "command",
"command": "python3 \"${CLAUDE_PLUGIN_ROOT}/hooks/guard_task_layout.py\"",
"timeout": 10

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Validate layout changes made outside file tools

When a task is created or modified through Bash—such as cp, mkdir, sed, or an analysis script—the new layout guard never runs because it is registered only for Edit|Write|NotebookEdit. This leaves arbitrary top-level files, missing READMEs, and invalid headings undetected; the finishing command does not provide a backstop because src/analysis_workflow/cli.py::layout still checks only stray, orphaned, and oversized outputs and can report Clean. Add a repository-wide layout validation to the finish check or otherwise cover non-file-tool changes.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in a06f447, as a Stop hook rather than in check layout: the installed package doesn't ship the plugin's task template, so it couldn't check headings. When a turn ends, the same guard checks the task directories with uncommitted changes (git status), which catches files made with cp, mkdir or a script, and earlier tasks are never scanned. It keeps the agent working once (stop_hook_active); tested.

…en a turn ends

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011aQpF4MA9v7dTVK1FqMMVJ

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a06f447a85

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread hooks/guard_task_layout.py Outdated
Comment on lines +133 to +134
status = subprocess.run(
["git", "status", "--porcelain=v1", "-z", "--untracked-files=all", "--", "analysis"],

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Check branch changes after they have been committed

When a shell command creates an off-layout file or malformed README and the agent commits it before ending the turn, this git status command returns no paths, so the Stop hook exits successfully. Fresh evidence in the current code is that the shell-change backstop is scoped exclusively to uncommitted status, despite the normal Finish flow committing and pushing before the turn ends; include task changes already committed on the branch or perform a full validation before allowing Stop.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 63fbac3: the check now diffs the working tree against the branch's merge base with the default branch, plus untracked files, so files committed in the same turn are caught; earlier tasks the branch doesn't touch are still not scanned. Tested by committing an off-layout file before Stop.

Comment thread hooks/guard_task_layout.py Outdated
Comment on lines +145 to +147
skip = entry[0] in "RC" # a rename's or copy's original path follows
if "D" not in entry[:2]:
paths.append(top / entry[3:])

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Retain deleted paths when identifying changed tasks

When README.md is removed through Bash, its status is D, and this filter discards the only path that identifies the changed task; tasks therefore remains empty and the later "no README.md" check never runs. Fresh evidence after the Stop-hook fix is the explicit exclusion of every deleted path here, so retain deleted paths for task discovery while skipping only inappropriate per-file validation.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 63fbac3: deleted paths now count for finding the changed task, so a deleted README is reported; a task directory renamed away (gone, not broken) is skipped. Both tested.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 63fbac3883

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

"""Paths under `analysis/` this branch changed, committed or not, deleted ones included, and untracked files."""
base = next((b for ref in ("origin/HEAD", "origin/main", "main") if (b := git(top, "merge-base", "HEAD", ref))), "")
names = git(top, "diff", "--name-only", "--no-renames", "-z", base.strip() or "HEAD", "--", "analysis").split("\0")
names += git(top, "ls-files", "--others", "--exclude-standard", "-z", "--", "analysis").split("\0")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Include ignored artifacts in the stop scan

When a script or Bash command creates an off-layout artifact matched by the repository's ignore rules—for example, analysis/topic/demo_v1/model.zarr, since adoption explicitly adds *.zarr—this command omits it because --exclude-standard applies the standard Git exclusions. The preceding diff also cannot see an untracked path, so the Stop hook returns success and leaves the invalid task layout undetected. Fresh evidence after the earlier shell-change fix is that its untracked-file backstop explicitly excludes ignored files; scan ignored paths as well while allowing their contents only beneath the permitted output directories.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not fixing: outputs come from task_paths and a hook blocks bare output paths, so an ignored artifact at a task's top is already prevented where it is written; ignored files never reach the PR; and scanning ignored paths would also walk a task-local .pixi environment. The cost is more than the case is worth.

Comment on lines +81 to +82
if TASK_DIR.match(part):
task = i

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Do not classify a lone versioned topic as a task

When a legitimate topic itself ends in _vN, writing a human notebook directly beneath it—such as analysis/cohort_v1/notes.ipynb—sets task to cohort_v1, after which problem() rejects the notebook as an invalid task entry. The skill permits notebooks flat under analysis/<topic>/ and imposes no topic-name restriction. Fresh evidence in the current revision is that the revised walk only passes over cohort_v1 when a later versioned directory replaces it, so the direct-notebook scenario from the earlier review remains broken.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolved by the convention instead of the hook, in 1eb2fb8: only task directories end in _vN, a topic never does. A marker heuristic (a README or scripts/ in the directory) only moves the ambiguity, since topics may have READMEs too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011aQpF4MA9v7dTVK1FqMMVJ
@Marius1311
Marius1311 merged commit 89a1c81 into main Oct 15, 2026
3 checks passed
@Marius1311
Marius1311 deleted the docs/deliverables branch October 15, 2026 09:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant