claude-dev-env 8.70.0 → 8.71.0

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.
@@ -0,0 +1,36 @@
1
+ # html-plan page template
2
+
3
+ Build a new artifact page from the html-plan skill. Load `house.css` from this folder after the plugin's `htmlplan.css`. The older [artifact page template](../artifact-page/README.md) stays available; use it when the request names it.
4
+
5
+ ## Get the skill
6
+
7
+ The html-plan plugin is the upstream source, and it stays read-only. Keep every local change in this folder.
8
+
9
+ 1. When the plugin is installed, run `/html-plan` or load the `html-plan` skill.
10
+ 2. When it is not installed, clone the source read-only and read the skill from it:
11
+
12
+ ```
13
+ git clone --depth 1 https://github.com/anthropics/claude-plugins-community <scratch folder>
14
+ git -C <scratch folder> checkout f60f0454df3045f724c43c6346ec80bdcc3472b2
15
+ ```
16
+
17
+ Read `html-plan/skills/html-plan/SKILL.md`, then `references/blocks.md` and `examples/scheduled-send.html` beside it. Link `runtime/htmlplan.css` and `runtime/htmlplan.js` from the page, and run `runtime/pack.mjs` to inline them.
18
+ 3. To install the plugin, run `claude plugin install html-plan@claude-community`. The person who owns the environment approves this step.
19
+
20
+ Codex reads the same `SKILL.md` from the clone in step 2.
21
+
22
+ ## House layer
23
+
24
+ `house.css` loads after `htmlplan.css`. It:
25
+
26
+ - sets the body text color and background from the theme tokens, so text keeps its contrast in dark mode,
27
+ - maps the gray text tokens to the full text color,
28
+ - sets accent and status colors that hold 7:1 contrast in light and dark,
29
+ - raises small text to 16px,
30
+ - removes opacity dimming on text.
31
+
32
+ Paste it into a `<style>` block after the plugin stylesheet, or link it beside the page.
33
+
34
+ ## Check before publishing
35
+
36
+ Render the page at 390px in light and dark. Every text node is 16px or larger and holds 7:1 contrast against its painted background. The page has no console errors and no horizontal scroll.
@@ -0,0 +1,26 @@
1
+ :root { color-scheme: light dark; --ink-2: var(--ink); --ink-3: var(--ink); --accent: #7a2e14; --green: #1c5426; --amber: #5f3f06; --red: #8f1d17; --on-accent: #ffffff; }
2
+ @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { --ink-2: var(--ink); --ink-3: var(--ink); --accent: #f6bba5; --green: #9fdcaa; --amber: #f2cc80; --red: #f7b3ab; --on-accent: #1f1e1d; } }
3
+ :root[data-theme="dark"] { --ink-2: var(--ink); --ink-3: var(--ink); --accent: #f6bba5; --green: #9fdcaa; --amber: #f2cc80; --red: #f7b3ab; --on-accent: #1f1e1d; }
4
+ body { background: var(--paper); color: var(--ink); font: 430 16px/1.6 var(--sans); }
5
+ small, code, bdi, .mk-cap, .mk-label, .mk-bar, .fig-cap, .c-lang, .c-lines, .c-body td,
6
+ .pl-num, .pl-chev, .pl-bdg, p.pl-claim, doc-claim > .pl-row > .pl-claim, .pl-body > p, .pl-body > ul, .pl-body > doc-note,
7
+ doc-ask::before, doc-ask label small, doc-ask label .sug, doc-ask label > span,
8
+ .nw-askrow .s, .nw-askrow .q small, .nw-btn, .nw-next, .nw-respond, .nw-cbtn, .fig-zoom, .tr-name, .tr-guide, .tr-note, .cl-note, .cl-loc, .mc-to, .mc-hint { font-size: 16px !important; }
9
+ .nw-cbtn, .cl-loc, .fig-zoom, .mc-ev[disabled], .nw-btn[disabled], svg.nw .msg.mc-past path, svg.nw .msg.mc-past text { opacity: 1 !important; }
10
+ .nw-next, .has-comment > .nw-cbtn, .nw-cbtn.on, .nw-askrow.todo .s, .nw-asks .ttl b.todo, .nw-pop.note .k { color: var(--on-accent) !important; }
11
+ .mk-frame.terminal .mk-bar { color: #e6e3dc; }
12
+ doc-note, doc-note > strong:first-child { font-size: 16px !important; }
13
+ :root { --blue: #1d4a85; --purple: #4f2f96; }
14
+ @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { --blue: #b9d3f5; --purple: #d3c3f5; } }
15
+ :root[data-theme="dark"] { --blue: #b9d3f5; --purple: #d3c3f5; }
16
+ doc-note, doc-note > strong:first-child, .pill, .kicker, .dek, .meta, h4, th, table, figcaption, .caption, details > summary, pre,
17
+ .nw-toc, .nw-toc a, .nw-toc a.h3, .nw-toc a.ask, .nw-toc .ttl, .nw-pop, .nw-pop .ref, .nw-pop textarea, .nw-sheet .hint, .nw-send-state,
18
+ .nw-sheet .body pre, .nw-asks .ttl, .nw-asks .ttl b, .nw-askrow, .nw-askrow .k, .nw-toast, .nw-pin-list, .nw-err, .nw-bar .nw-respond .n,
19
+ doc-claim[data-l="1"] > .pl-row > .pl-num, doc-claim[data-l="2"] > .pl-row > .pl-claim { font-size: 16px !important; }
20
+ .has-comment > .nw-cbtn, .nw-cbtn.on, .nw-bar .nw-respond .n, .nw-bar .nw-next { background: var(--accent); }
21
+ .nw-bar .nw-respond .n.ok { background: var(--green); color: var(--on-accent); }
22
+ .nw-bar .nw-respond .n { color: var(--on-accent); }
23
+ doc-changes, doc-changes b, .ch-tag, .ch-n, .q-head, .q-via, .q-from, .q-at, .q-body { font-size: 16px !important; }
24
+ .cl-head, .cl-kind, .cl-title, .cl-counts, .cl-counts b, .cl-nm, .cl-rail, .cl-tg, .c-cap, .c-pin b, .mc-now, .mc-now b, .mc-now i, .mc-now span, .nw-pin-dot, svg.nw text, svg.nw .node text.sub, svg.nw .node text.more, svg.nw .edge text, svg.nw .group text { font-size: 16px !important; }
25
+ .cl-tg, .tr-guide { color: var(--ink); }
26
+ .nw-pin-dot { color: var(--on-accent); }
@@ -10,7 +10,7 @@ This family injects reminders and task guidance when an agent starts, resumes, s
10
10
  - `session/advisor_rules_prompt.py` injects advisor guidance when the built-in advisor is enabled.
11
11
  - `session/orchestrator_auto_starter.py` injects an orchestrator directive when its environment flag is enabled.
12
12
  - `session/issue_tracker_session_starter.py` injects issue tracker guidance when enabled for a registered repository.
13
- - `session/artifact_template_pointer.py` points an agent that starts an artifact page at `docs/templates/artifact-page/README.md`, which names the tracker template and the diagram template and which ask each fits.
13
+ - `session/artifact_template_pointer.py` points an agent that starts an artifact page at `docs/templates/html-plan/README.md`. When the request names the older artifact page template, it points at `docs/templates/artifact-page/README.md`, which names the tracker template and the diagram template and which ask each fits.
14
14
  - `advisory/auto_mode_denial_quick_fix.py` proposes one `autoMode.allow` entry and a PowerShell block that writes it after an auto mode denial. It never retries the denied call.
15
15
 
16
16
  ## When it fires
@@ -32,7 +32,7 @@ Preconditions:
32
32
  - **Advisor guidance.** Input is SessionStart with `advisorModel` set. Run `python -m pytest packages/claude-dev-env/hooks/session/test_advisor_rules_prompt.py -q`. The adjacent test observes guidance only when the advisor setting is enabled.
33
33
  - **Orchestrator start.** Input is SessionStart with its opt-in flag set. Run `python -m pytest packages/claude-dev-env/hooks/session/test_orchestrator_auto_starter.py -q`. The adjacent test observes an orchestrator directive.
34
34
  - **Issue tracker start.** Input is SessionStart with its opt-in flag and a registered checkout. Run `python -m pytest packages/claude-dev-env/hooks/session/test_issue_tracker_session_starter.py -q`. The adjacent test observes issue tracker context.
35
- - **Artifact template pointer.** Input is an `Artifact` quickstart call. Run `python -m pytest packages/claude-dev-env/hooks/session/test_artifact_template_pointer.py -q`. The adjacent test observes the template path in `additionalContext`, and silence on a publish call or another skill.
35
+ - **Artifact template pointer.** Input is an `Artifact` quickstart call. Run `python -m pytest packages/claude-dev-env/hooks/session/test_artifact_template_pointer.py -q`. The adjacent test observes the html-plan path ahead of the template path in `additionalContext`, and silence on a publish call or another skill.
36
36
  - **Denial quick fix.** Input is a `PermissionDenied` event with a bracketed rule label and a classifier verdict. Run `python -m pytest packages/claude-dev-env/hooks/advisory/test_auto_mode_denial_quick_fix.py -q`. The adjacent test observes the named rule, the allow entry, and the PowerShell block; a denial with no verdict gets a note and no block.
37
37
 
38
38
  ## Gotchas
@@ -9,6 +9,8 @@ __all__ = [
9
9
  "ARTIFACT_QUICKSTART_ACTION",
10
10
  "ARTIFACT_TEMPLATE_PATH",
11
11
  "ARTIFACT_TOOL_NAME",
12
+ "HTML_PLAN_TEMPLATE_README_PATH",
13
+ "POINTER_ALTERNATIVE_PREFIX",
12
14
  "POINTER_TEXT_PREFIX",
13
15
  "SKILL_NAME_INPUT_KEY",
14
16
  "SKILL_TOOL_NAME",
@@ -21,7 +23,11 @@ ARTIFACT_QUICKSTART_ACTION = "quickstart"
21
23
  SKILL_TOOL_NAME = "Skill"
22
24
  SKILL_NAME_INPUT_KEY = "skill"
23
25
  ALL_ARTIFACT_DESIGN_SKILL_NAMES = frozenset({"artifact-design"})
24
- ARTIFACT_TEMPLATE_PATH = (
25
- Path(__file__).resolve().parents[2] / "docs" / "templates" / "artifact-page" / "README.md"
26
+ TEMPLATES_DIRECTORY = Path(__file__).resolve().parents[2] / "docs" / "templates"
27
+ ARTIFACT_TEMPLATE_PATH = TEMPLATES_DIRECTORY / "artifact-page" / "README.md"
28
+ HTML_PLAN_TEMPLATE_README_PATH = TEMPLATES_DIRECTORY / "html-plan" / "README.md"
29
+ POINTER_TEXT_PREFIX = "Build this artifact page from the html-plan skill, following "
30
+ POINTER_ALTERNATIVE_PREFIX = (
31
+ ". When the request names the older artifact page template,"
32
+ " pick the one that fits the ask from "
26
33
  )
27
- POINTER_TEXT_PREFIX = "Pick the artifact page template that fits the ask from "
@@ -1,8 +1,16 @@
1
1
  """Behavioral tests for the artifact template pointer's path."""
2
2
 
3
- from hooks_constants.artifact_template_pointer_constants import ARTIFACT_TEMPLATE_PATH
3
+ from hooks_constants.artifact_template_pointer_constants import (
4
+ ARTIFACT_TEMPLATE_PATH,
5
+ HTML_PLAN_TEMPLATE_README_PATH,
6
+ )
4
7
 
5
8
 
6
9
  def test_template_path_names_the_packaged_template_file() -> None:
7
10
  assert ARTIFACT_TEMPLATE_PATH.is_file()
8
11
  assert ARTIFACT_TEMPLATE_PATH.parent.joinpath("README.md").is_file()
12
+
13
+
14
+ def test_html_plan_readme_path_names_the_packaged_readme_and_house_stylesheet() -> None:
15
+ assert HTML_PLAN_TEMPLATE_README_PATH.is_file()
16
+ assert HTML_PLAN_TEMPLATE_README_PATH.parent.joinpath("house.css").is_file()
@@ -1,9 +1,10 @@
1
1
  #!/usr/bin/env python3
2
- """PreToolUse hook: point an agent about to build an artifact page at the template.
2
+ """PreToolUse hook: point an agent about to build an artifact page at html-plan.
3
3
 
4
4
  Registered on ``Artifact|Skill``. It adds one line of ``additionalContext``
5
- naming ``docs/templates/artifact-page/template.html`` when a session starts a
6
- new artifact page:
5
+ naming ``docs/templates/html-plan/README.md`` as the default and
6
+ ``docs/templates/artifact-page/README.md`` as the alternative when a
7
+ session starts a new artifact page:
7
8
 
8
9
  ::
9
10
 
@@ -31,6 +32,8 @@ from hooks_constants.artifact_template_pointer_constants import (
31
32
  ARTIFACT_QUICKSTART_ACTION,
32
33
  ARTIFACT_TEMPLATE_PATH,
33
34
  ARTIFACT_TOOL_NAME,
35
+ HTML_PLAN_TEMPLATE_README_PATH,
36
+ POINTER_ALTERNATIVE_PREFIX,
34
37
  POINTER_TEXT_PREFIX,
35
38
  SKILL_NAME_INPUT_KEY,
36
39
  SKILL_TOOL_NAME,
@@ -77,7 +80,10 @@ def decide_hook_output(all_hook_fields: dict[str, object]) -> dict[str, object]
77
80
  return {
78
81
  HOOK_SPECIFIC_OUTPUT_KEY: {
79
82
  HOOK_EVENT_NAME_KEY: PRE_TOOL_USE_EVENT_NAME,
80
- ADDITIONAL_CONTEXT_KEY: f"{POINTER_TEXT_PREFIX}{ARTIFACT_TEMPLATE_PATH}.",
83
+ ADDITIONAL_CONTEXT_KEY: (
84
+ f"{POINTER_TEXT_PREFIX}{HTML_PLAN_TEMPLATE_README_PATH}"
85
+ f"{POINTER_ALTERNATIVE_PREFIX}{ARTIFACT_TEMPLATE_PATH}."
86
+ ),
81
87
  }
82
88
  }
83
89
 
@@ -10,7 +10,10 @@ for each_sys_path_entry in (str(_SESSION_DIR), str(_HOOKS_ROOT)):
10
10
  sys.path.insert(0, each_sys_path_entry)
11
11
 
12
12
  import artifact_template_pointer
13
- from hooks_constants.artifact_template_pointer_constants import ARTIFACT_TEMPLATE_PATH
13
+ from hooks_constants.artifact_template_pointer_constants import (
14
+ ARTIFACT_TEMPLATE_PATH,
15
+ HTML_PLAN_TEMPLATE_README_PATH,
16
+ )
14
17
 
15
18
  HOOK_SCRIPT = Path(__file__).resolve().parent / "artifact_template_pointer.py"
16
19
 
@@ -34,7 +37,10 @@ def test_artifact_quickstart_gets_the_template_pointer() -> None:
34
37
  hook_output = json.loads(_run_hook(_payload("Artifact", {"action": "quickstart", "intent": "other"})))
35
38
  specific_output = hook_output["hookSpecificOutput"]
36
39
  assert specific_output["hookEventName"] == "PreToolUse"
37
- assert str(ARTIFACT_TEMPLATE_PATH) in specific_output["additionalContext"]
40
+ pointer_text = specific_output["additionalContext"]
41
+ assert pointer_text.index(str(HTML_PLAN_TEMPLATE_README_PATH)) < pointer_text.index(
42
+ str(ARTIFACT_TEMPLATE_PATH)
43
+ )
38
44
  assert "permissionDecision" not in specific_output
39
45
 
40
46
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-dev-env",
3
- "version": "8.70.0",
3
+ "version": "8.71.0",
4
4
  "description": "Claude Code development standards — rules, hooks, agents, commands, and skills",
5
5
  "type": "module",
6
6
  "bin": {