principles 0.0.1
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.
- checksums.yaml +7 -0
- data/exe/principles +10 -0
- data/lib/principles/after_commit_hook_options.rb +44 -0
- data/lib/principles/cli.rb +149 -0
- data/lib/principles/command_line.rb +188 -0
- data/lib/principles/command_routes.rb +60 -0
- data/lib/principles/controllers/acknowledgement.rb +106 -0
- data/lib/principles/controllers/answer.rb +172 -0
- data/lib/principles/controllers/audit.rb +203 -0
- data/lib/principles/controllers/audit_completion.rb +113 -0
- data/lib/principles/controllers/command.rb +201 -0
- data/lib/principles/controllers/correction.rb +99 -0
- data/lib/principles/controllers/help.rb +107 -0
- data/lib/principles/controllers/inventory.rb +181 -0
- data/lib/principles/controllers/mapping.rb +56 -0
- data/lib/principles/controllers/member_entries.rb +149 -0
- data/lib/principles/controllers/members_a_commit_changed.rb +43 -0
- data/lib/principles/controllers/members_to_assess.rb +160 -0
- data/lib/principles/controllers/meta_principle_setup.rb +92 -0
- data/lib/principles/controllers/repoint.rb +68 -0
- data/lib/principles/controllers/running_tool.rb +41 -0
- data/lib/principles/data/audit_files.rb +96 -0
- data/lib/principles/data/bounded_file.rb +45 -0
- data/lib/principles/data/candidate_files_found.rb +105 -0
- data/lib/principles/data/command-steps.json +305 -0
- data/lib/principles/data/command_steps_file.rb +50 -0
- data/lib/principles/data/expected_type.rb +71 -0
- data/lib/principles/data/ignored_by_git.rb +54 -0
- data/lib/principles/data/json_text.rb +57 -0
- data/lib/principles/data/known_fields.rb +42 -0
- data/lib/principles/data/linked_path.rb +102 -0
- data/lib/principles/data/map_files.rb +104 -0
- data/lib/principles/data/principle_id.rb +32 -0
- data/lib/principles/data/principles_subfolder.rb +93 -0
- data/lib/principles/data/project_files.rb +109 -0
- data/lib/principles/data/repository.rb +165 -0
- data/lib/principles/data/running_version.rb +44 -0
- data/lib/principles/data/schema_check.rb +139 -0
- data/lib/principles/data/schemas/acknowledgement-answer.schema.json +25 -0
- data/lib/principles/data/schemas/answer-guide.schema.json +99 -0
- data/lib/principles/data/schemas/assessment-answer.schema.json +332 -0
- data/lib/principles/data/schemas/audit-record.schema.json +277 -0
- data/lib/principles/data/schemas/command-steps.schema.json +83 -0
- data/lib/principles/data/schemas/correction-answer-guide.schema.json +68 -0
- data/lib/principles/data/schemas/correction-answer.schema.json +306 -0
- data/lib/principles/data/schemas/member-map.schema.json +39 -0
- data/lib/principles/data/schemas/repointing-answer.schema.json +44 -0
- data/lib/principles/error.rb +102 -0
- data/lib/principles/invocation_options.rb +77 -0
- data/lib/principles/models/accepted_loading.rb +36 -0
- data/lib/principles/models/acknowledgement.rb +203 -0
- data/lib/principles/models/activation.rb +64 -0
- data/lib/principles/models/agent_loads.rb +64 -0
- data/lib/principles/models/answer_fields.rb +67 -0
- data/lib/principles/models/answer_place.rb +53 -0
- data/lib/principles/models/answer_text.rb +37 -0
- data/lib/principles/models/answered_time.rb +65 -0
- data/lib/principles/models/assessment_answer.rb +131 -0
- data/lib/principles/models/assessment_basis.rb +47 -0
- data/lib/principles/models/assessment_report.rb +62 -0
- data/lib/principles/models/audit.rb +200 -0
- data/lib/principles/models/audit_record.rb +249 -0
- data/lib/principles/models/audit_records.rb +103 -0
- data/lib/principles/models/audit_start.rb +96 -0
- data/lib/principles/models/audited_member_lines.rb +45 -0
- data/lib/principles/models/candidate_files.rb +66 -0
- data/lib/principles/models/candidate_inventory.rb +67 -0
- data/lib/principles/models/candidate_listing.rb +32 -0
- data/lib/principles/models/carried_assessments.rb +76 -0
- data/lib/principles/models/check_since_last_audit.rb +61 -0
- data/lib/principles/models/cited_files.rb +39 -0
- data/lib/principles/models/command_steps.rb +270 -0
- data/lib/principles/models/commits_brought_in.rb +27 -0
- data/lib/principles/models/commits_since_base.rb +32 -0
- data/lib/principles/models/correction_answer.rb +66 -0
- data/lib/principles/models/correction_basis.rb +70 -0
- data/lib/principles/models/dated_line.rb +29 -0
- data/lib/principles/models/decided_prior_findings.rb +106 -0
- data/lib/principles/models/declared_map_changes.rb +156 -0
- data/lib/principles/models/disposition.rb +233 -0
- data/lib/principles/models/entry_file.rb +65 -0
- data/lib/principles/models/entry_files.rb +46 -0
- data/lib/principles/models/evidence_item.rb +48 -0
- data/lib/principles/models/evidence_lines_since.rb +57 -0
- data/lib/principles/models/evidence_replacements.rb +99 -0
- data/lib/principles/models/finding_write_ups.rb +108 -0
- data/lib/principles/models/findings_left_open.rb +34 -0
- data/lib/principles/models/first_raised_claim.rb +128 -0
- data/lib/principles/models/frontmatter_fields.rb +128 -0
- data/lib/principles/models/hook_commands.rb +100 -0
- data/lib/principles/models/ignored_candidates.rb +46 -0
- data/lib/principles/models/json_digest.rb +35 -0
- data/lib/principles/models/json_path_query.rb +131 -0
- data/lib/principles/models/json_path_selectors.rb +64 -0
- data/lib/principles/models/json_path_string.rb +76 -0
- data/lib/principles/models/kept_prior_finding.rb +70 -0
- data/lib/principles/models/last_completed_revision.rb +70 -0
- data/lib/principles/models/line_span.rb +49 -0
- data/lib/principles/models/loaded_files.rb +60 -0
- data/lib/principles/models/loading_decision.rb +45 -0
- data/lib/principles/models/loading_facts.rb +45 -0
- data/lib/principles/models/loads_to_check.rb +93 -0
- data/lib/principles/models/locate_refusal.rb +23 -0
- data/lib/principles/models/located_text.rb +43 -0
- data/lib/principles/models/locator.rb +52 -0
- data/lib/principles/models/map_members.rb +171 -0
- data/lib/principles/models/markdown_file.rb +92 -0
- data/lib/principles/models/member.rb +171 -0
- data/lib/principles/models/member_assessments.rb +144 -0
- data/lib/principles/models/member_elsewhere.rb +74 -0
- data/lib/principles/models/member_file.rb +156 -0
- data/lib/principles/models/member_grounds.rb +32 -0
- data/lib/principles/models/member_history.rb +68 -0
- data/lib/principles/models/member_lines.rb +95 -0
- data/lib/principles/models/member_loads.rb +197 -0
- data/lib/principles/models/member_map.rb +219 -0
- data/lib/principles/models/member_map_history.rb +143 -0
- data/lib/principles/models/member_maps.rb +185 -0
- data/lib/principles/models/member_moves.rb +95 -0
- data/lib/principles/models/member_problems.rb +253 -0
- data/lib/principles/models/member_sighting.rb +176 -0
- data/lib/principles/models/member_snapshots.rb +36 -0
- data/lib/principles/models/member_state.rb +35 -0
- data/lib/principles/models/members_elsewhere.rb +46 -0
- data/lib/principles/models/members_sharing_lines.rb +116 -0
- data/lib/principles/models/meta_principle.rb +51 -0
- data/lib/principles/models/missing_files.rb +85 -0
- data/lib/principles/models/misspelt_member_id.rb +45 -0
- data/lib/principles/models/open_finding.rb +221 -0
- data/lib/principles/models/open_findings_elsewhere.rb +45 -0
- data/lib/principles/models/other_principles.rb +47 -0
- data/lib/principles/models/placement.rb +42 -0
- data/lib/principles/models/plain_text_file.rb +32 -0
- data/lib/principles/models/principles_folder_move.rb +59 -0
- data/lib/principles/models/principles_package.rb +53 -0
- data/lib/principles/models/prior_finding_decision.rb +162 -0
- data/lib/principles/models/prior_finding_outcomes.rb +60 -0
- data/lib/principles/models/prior_findings.rb +109 -0
- data/lib/principles/models/problem_report.rb +110 -0
- data/lib/principles/models/project.rb +214 -0
- data/lib/principles/models/project_history.rb +203 -0
- data/lib/principles/models/record_judged_against.rb +42 -0
- data/lib/principles/models/recorded_entry.rb +93 -0
- data/lib/principles/models/recorded_finding.rb +97 -0
- data/lib/principles/models/recorded_findings.rb +58 -0
- data/lib/principles/models/recorded_members.rb +149 -0
- data/lib/principles/models/repoint.rb +112 -0
- data/lib/principles/models/reported_check.rb +130 -0
- data/lib/principles/models/request_id.rb +70 -0
- data/lib/principles/models/runs_from.rb +36 -0
- data/lib/principles/models/skill_loads.rb +123 -0
- data/lib/principles/models/still_holds_restatement.rb +87 -0
- data/lib/principles/models/text_size.rb +26 -0
- data/lib/principles/models/uncommitted_outside_the_map.rb +30 -0
- data/lib/principles/models/waits_on.rb +58 -0
- data/lib/principles/models/write_up_opening.rb +93 -0
- data/lib/principles/models/write_up_pointer.rb +50 -0
- data/lib/principles/models/write_up_repoint.rb +39 -0
- data/lib/principles/prose_list.rb +23 -0
- data/lib/principles/supported_ruby.rb +93 -0
- data/lib/principles/version.rb +11 -0
- data/lib/principles/views/acknowledged_since_last_audit.rb +34 -0
- data/lib/principles/views/acknowledgement_result.rb +44 -0
- data/lib/principles/views/activation_in_hand.rb +47 -0
- data/lib/principles/views/assessment_request.rb +131 -0
- data/lib/principles/views/audit_changes.rb +79 -0
- data/lib/principles/views/audit_commit.rb +55 -0
- data/lib/principles/views/audit_result.rb +147 -0
- data/lib/principles/views/candidate_files_result.rb +95 -0
- data/lib/principles/views/check_result_template.rb +75 -0
- data/lib/principles/views/diff_since_last_audit.rb +29 -0
- data/lib/principles/views/findings_result.rb +45 -0
- data/lib/principles/views/help.rb +119 -0
- data/lib/principles/views/invocation.rb +66 -0
- data/lib/principles/views/landed_since_base.rb +27 -0
- data/lib/principles/views/lines_shared_with_member.rb +111 -0
- data/lib/principles/views/loads_to_check_result.rb +45 -0
- data/lib/principles/views/map_result.rb +169 -0
- data/lib/principles/views/member_change_since_baseline.rb +58 -0
- data/lib/principles/views/member_repairs.rb +82 -0
- data/lib/principles/views/members_a_commit_changed.rb +66 -0
- data/lib/principles/views/members_with_no_baseline.rb +56 -0
- data/lib/principles/views/meta_principle_passage.rb +23 -0
- data/lib/principles/views/meta_principle_result.rb +170 -0
- data/lib/principles/views/open_findings_elsewhere_result.rb +32 -0
- data/lib/principles/views/open_findings_line.rb +125 -0
- data/lib/principles/views/other_principles_unjudged_result.rb +32 -0
- data/lib/principles/views/outside_the_map_result.rb +31 -0
- data/lib/principles/views/package_since_last_audit_result.rb +34 -0
- data/lib/principles/views/principle_read_result.rb +86 -0
- data/lib/principles/views/principle_with_changed_members.rb +26 -0
- data/lib/principles/views/principles_with_no_completed_audit.rb +30 -0
- data/lib/principles/views/printed_principle.rb +45 -0
- data/lib/principles/views/prior_finding_decisions_result.rb +35 -0
- data/lib/principles/views/prior_findings_result.rb +80 -0
- data/lib/principles/views/problem_lines.rb +84 -0
- data/lib/principles/views/problem_result.rb +107 -0
- data/lib/principles/views/prompts/acknowledge-a-change/say-whether-the-change-keeps-the-meaning.md +12 -0
- data/lib/principles/views/prompts/answer-any-judgement-request/what-a-self-audit-cannot-show.md +6 -0
- data/lib/principles/views/prompts/assess-every-member/answer-guide.json +63 -0
- data/lib/principles/views/prompts/assess-every-member/assess-each-member-and-the-set.md +12 -0
- data/lib/principles/views/prompts/assess-every-member/check-roles-other-principles-give-these-lines.md +7 -0
- data/lib/principles/views/prompts/assess-every-member/decide-each-member-loading.md +17 -0
- data/lib/principles/views/prompts/assess-every-member/decide-each-prior-finding.md +38 -0
- data/lib/principles/views/prompts/assess-every-member/give-problem-evidence-at-still-holds.md +2 -0
- data/lib/principles/views/prompts/assess-every-member/give-the-evidence-a-prior-finding-lacks.md +7 -0
- data/lib/principles/views/prompts/assess-every-member/have-a-changed-check-reviewed-before-running-it.md +4 -0
- data/lib/principles/views/prompts/assess-every-member/have-a-new-check-reviewed-before-running-it.md +3 -0
- data/lib/principles/views/prompts/assess-every-member/have-hidden-characters-in-a-check-explained.md +4 -0
- data/lib/principles/views/prompts/assess-every-member/judge-acknowledged-edits-together.md +6 -0
- data/lib/principles/views/prompts/assess-every-member/judge-the-keeping-against-the-other-principles.md +7 -0
- data/lib/principles/views/prompts/assess-every-member/judge-the-keeping-under-the-release-since-the-last-audit.md +10 -0
- data/lib/principles/views/prompts/assess-every-member/judge-the-set-with-carried-assessments.md +10 -0
- data/lib/principles/views/prompts/assess-every-member/keep-the-last-review-basis-unless-you-give-a-new-one.md +1 -0
- data/lib/principles/views/prompts/assess-every-member/name-another-principles-open-finding-rather-than-raise-it.md +9 -0
- data/lib/principles/views/prompts/assess-every-member/read-whether-each-prior-finding-s-evidence-changed.md +12 -0
- data/lib/principles/views/prompts/assess-every-member/run-a-named-check-at-every-full-audit.md +2 -0
- data/lib/principles/views/prompts/assess-every-member/run-the-check-then-report-it.md +2 -0
- data/lib/principles/views/prompts/assess-every-member/run-the-reviewed-check-and-say-what-its-review-rested-on.md +6 -0
- data/lib/principles/views/prompts/assess-every-member/uncommitted-files-outside-the-map.md +4 -0
- data/lib/principles/views/prompts/assess-every-member/why-each-member-is-judged-again.md +24 -0
- data/lib/principles/views/prompts/dispose-of-each-finding/answer-guide.json +34 -0
- data/lib/principles/views/prompts/dispose-of-each-finding/fix-or-record-each-finding.md +24 -0
- data/lib/principles/views/prompts/find-a-principle-to-map/ask-the-owner-before-mapping.md +1 -0
- data/lib/principles/views/prompts/find-a-principle-to-map/choose-one-principle.md +5 -0
- data/lib/principles/views/prompts/find-a-principle-to-map/owner-ask-ignored-folders.md +2 -0
- data/lib/principles/views/prompts/find-a-principle-to-map/owner-ask-ignored.md +3 -0
- data/lib/principles/views/prompts/find-a-principle-to-map/owner-ask-possibly-test-data.md +2 -0
- data/lib/principles/views/prompts/find-a-principle-to-map/owner-ask-untracked.md +2 -0
- data/lib/principles/views/prompts/find-a-principle-to-map/what-each-command-writes.md +4 -0
- data/lib/principles/views/prompts/find-a-principle-to-map/where-the-inventory-looks.md +10 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/add-member.md +45 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/change-activation.md +21 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/change-description.md +2 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/change-member-check.md +17 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/change-member-role.md +9 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/create-principle.md +6 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/every-command-and-how-they-chain.md +28 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/list-candidate-files.md +17 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/list-member-problems.md +73 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/list-open-findings.md +71 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/list-principles.md +7 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/move-member.md +11 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/remove-member-check.md +10 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/remove-member.md +6 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/show-answer-check.md +16 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/show-audit.md +20 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/show-meta-principle-passage.md +52 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/show-principle.md +86 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/start-audit.md +68 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/submit-answer.md +56 -0
- data/lib/principles/views/prompts/repoint-write-ups/point-each-moved-write-up-at-its-new-place.md +10 -0
- data/lib/principles/views/prompts/report-after-a-commit/it-refused-after-the-commits-touched-the-maps.md +2 -0
- data/lib/principles/views/prompts/report-after-a-commit/others-are-still-listed.md +1 -0
- data/lib/principles/views/prompts/report-after-a-commit/the-commits-changed-these-members.md +2 -0
- data/lib/principles/views/prompts/report-after-a-commit/this-command-shows-each-one.md +1 -0
- data/lib/principles/views/prompts/report-the-completed-audit/commit-only-what-the-audit-changed.md +2 -0
- data/lib/principles/views/prompts/report-the-completed-audit/replace-the-default-commit-message.md +4 -0
- data/lib/principles/views/prompts/report-the-completed-audit/what-completion-means.md +2 -0
- data/lib/principles/views/prompts/set-principles-up/entry-file-passage.md +3 -0
- data/lib/principles/views/prompts/set-principles-up/name-the-step-each-member-lacks.md +15 -0
- data/lib/principles/views/prompts/set-principles-up/place-the-passage-with-the-user.md +31 -0
- data/lib/principles/views/prompts/set-principles-up/set-up-first.md +2 -0
- data/lib/principles/views/prompts/set-principles-up/what-the-passage-presumes.md +4 -0
- data/lib/principles/views/prompts/start-a-session/act-on-the-open-findings.md +5 -0
- data/lib/principles/views/prompts/start-a-session/it-returns-after-each-clear-or-compaction-too.md +1 -0
- data/lib/principles/views/prompts/start-a-session/it-returns-at-each-session-start.md +1 -0
- data/lib/principles/views/prompts/start-a-session/raise-them-at-the-next-pause.md +1 -0
- data/lib/principles/views/prompts/start-a-session/raise-them-before-the-first-task.md +1 -0
- data/lib/principles/views/prompts.rb +71 -0
- data/lib/principles/views/repoint_result.rb +80 -0
- data/lib/principles/views/request_part.rb +26 -0
- data/lib/principles/views/request_parts.rb +26 -0
- data/lib/principles/views/shell_word.rb +29 -0
- data/lib/principles/views/visible_text.rb +26 -0
- data/lib/principles/views/workflow_diagram.rb +77 -0
- data/lib/principles.rb +5 -0
- metadata +326 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
Shows each member of principle ID, where its text is now and whether it changed since the last audit. Audit when a
|
|
2
|
+
member is changed, unassessed, locator_lost or unavailable. A member that is locator_lost or unavailable carries
|
|
3
|
+
`repair_with`: a `move-member` with its `NEW_PATH`, `HEADING` or `QUERY` to fill in, for a section or passage a
|
|
4
|
+
second `move-member` for text moved into another file, and a `remove-member`. Run the one that fits;
|
|
5
|
+
`next_action` names those members.
|
|
6
|
+
|
|
7
|
+
Each member's `loads` says, for each host this tool derives, when that host loads the member's file into the agent's
|
|
8
|
+
context. Only `claude_code` is derived; Codex is not yet. The derivation follows Claude Code's documented loading
|
|
9
|
+
from the file's path alone, for a session started at the project root, not what loaded in any session:
|
|
10
|
+
|
|
11
|
+
- `session_start`: the project's `CLAUDE.md`, `.claude/CLAUDE.md` or `CLAUDE.local.md`, in every session.
|
|
12
|
+
- `on_files` with `files`: one of those files in a folder below the root, once a file in that folder is read,
|
|
13
|
+
written or edited.
|
|
14
|
+
- `session_start` too: a rule in `.claude/rules/`, or a folder within it, without a `paths` field in its
|
|
15
|
+
frontmatter.
|
|
16
|
+
- `on_files` with `paths_field`: a rule with a `paths` field, once a file it matches is read, written or edited.
|
|
17
|
+
`paths_field` is the field's lines as written; this tool does not read the globs, so read them yourself.
|
|
18
|
+
- `on_invocation`: a skill's `SKILL.md` in `.claude/skills/NAME/`, whose body loads when the skill is invoked.
|
|
19
|
+
`invoked_by` is `model_or_person`, or `person` when its frontmatter says `disable-model-invocation: true`, so only
|
|
20
|
+
a person's `/NAME` invokes it. This tool reads that field only as a plain `true` or `false` on its line.
|
|
21
|
+
`description` says when the skill's description, which tells the model the skill exists, loads: `session_start`;
|
|
22
|
+
`on_files` with `paths_field`, for a skill with a `paths` field; `on_files` with `files`, for a skill in a folder
|
|
23
|
+
below the root; or `not_loaded`, for a skill only a person invokes. Other files in a skill's folder are
|
|
24
|
+
`no_known_carrier`: the skill's body may tell the agent to read them. A member that is the skill's description
|
|
25
|
+
field, by a query that names its `description` field such as `$.description`, has `skill_part: description` and
|
|
26
|
+
the description's moment as its own `when`, with only its own `member_bytes`, since the file's size is the body's
|
|
27
|
+
cost; any other frontmatter field's member gets the body's answer.
|
|
28
|
+
- `on_delegation` with `context: subagent`: a subagent's definition, a `.md` file at any depth in `.claude/agents/`.
|
|
29
|
+
Its body is the subagent's own system prompt, loaded in the subagent's context, not the main session's, when
|
|
30
|
+
Claude delegates to it; `description` is `session_start`, since Claude reads every subagent's description to
|
|
31
|
+
decide when to delegate. An agents folder below the root, or an agent file without a `description` field, such as
|
|
32
|
+
a note kept beside the agents, is `not_determined`.
|
|
33
|
+
- `not_determined`: This tool knows the file is a rule, a skill or an agent but not when it loads.
|
|
34
|
+
`frontmatter_refused` names the code this tool refused its frontmatter with, so read the frontmatter; `not_derived`
|
|
35
|
+
names a kind it does not derive yet, such as a rules folder below the project root.
|
|
36
|
+
- `no_known_carrier`: This tool knows no Claude Code facility that loads this path by itself. An `@` import from
|
|
37
|
+
another instruction file, or a user-level file, may still load it; read the importing file to check.
|
|
38
|
+
|
|
39
|
+
Whatever `when` says, `named_in_hooks` lists each project hook whose command names the member's file: its `settings`
|
|
40
|
+
file, `event`, `matcher` (left out when the event has none), and `command` and `args` as written. A command names
|
|
41
|
+
the file when it or one of its args gives the file's path from the project root, bare or after
|
|
42
|
+
`$CLAUDE_PROJECT_DIR`; a path reached another way, such as after a `cd`, is not recognised. This tool does not run
|
|
43
|
+
the command, so a name is not proof the hook runs the file, and it says nothing of whether the hook's output reaches
|
|
44
|
+
context: that depends on the event and on what the command prints, so read the event in Claude Code's hooks
|
|
45
|
+
documentation and the script. It reads only command handlers in `.claude/settings.json` and
|
|
46
|
+
`.claude/settings.local.json`; the local file is this checkout's own, and a handler in both runs once. It reads the
|
|
47
|
+
local file even where git ignores it, as Claude Code runs its hooks either way, so an owner's personal commands can
|
|
48
|
+
show here; list-candidate-files leaves an ignored file out of what it lists to map, not out of what loads. This tool
|
|
49
|
+
only prints them here and never writes them to a map or an audit record; if you quote one in an audit answer, that
|
|
50
|
+
answer is written to the audit record, which the project commits, so leave a personal command out of it. It does not
|
|
51
|
+
read user, managed, plugin or skill and agent frontmatter hooks, `prompt` or `agent` handlers, or `disableAllHooks`.
|
|
52
|
+
`hook_settings_not_read` names each of those two settings files this tool could not read, with its refusal code, so
|
|
53
|
+
an unreadable file is not taken for one without hooks.
|
|
54
|
+
|
|
55
|
+
A carrier loads its whole file, so `file_bytes` is the file's size, shared by every member in it, and
|
|
56
|
+
`estimated_tokens` is its characters divided by four, rounded up: an estimate, not a tokenizer count. For a skill,
|
|
57
|
+
they are what its body costs once invoked, and for an agent what its body costs in the subagent's context; the
|
|
58
|
+
description is a smaller part of the file. A `loads` without `context` loads into the main session's context.
|
|
59
|
+
`member_bytes` and `member_tokens` are the member's own lines, its share of that file, which moving the member out
|
|
60
|
+
of it would save; for a member that is its whole file they equal `file_bytes` and `estimated_tokens`, and they are
|
|
61
|
+
left out when this tool cannot find the member in its file.
|
|
62
|
+
Those lines may be other members' too: `overlaps` names this principle's members sharing a line with it, `same_lines_as`
|
|
63
|
+
those spanning exactly its lines, and `mapped_elsewhere` other principles' members, each with its role, `first_line`,
|
|
64
|
+
`last_line`, and `same_lines` when spanning exactly the same lines, `spans_these_lines` when its lines include all of
|
|
65
|
+
this member's, or `within_these_lines` when they all lie within this member's. Each is left out when none shares a line.
|
|
66
|
+
Before narrowing a section to save its `member_bytes`, check whose lines they are.
|
|
67
|
+
|
|
68
|
+
Members in one file each show that file's size, so adding up the members counts a shared file once per member.
|
|
69
|
+
`files_loaded` lists each file the members load once, with its `path`, when it loads and its size, as a member's
|
|
70
|
+
`loads.claude_code` gives them, leaving out a file with no known carrier; the hooks that name a file show on its
|
|
71
|
+
members. `session_start_total` adds up the files that load whole at session start, the one moment
|
|
72
|
+
they all load together; the files that load on files, on invocation or on delegation each load apart, so they are not
|
|
73
|
+
added up. Beside them, `descriptions` gives the `count` of skill and agent descriptions that load at session start
|
|
74
|
+
while their bodies wait, with their `description_bytes` and `description_tokens`: for a skill, its `description` and
|
|
75
|
+
`when_to_use` lines together, cut at 1,536 characters as Claude Code cuts each skill's listing
|
|
76
|
+
(code.claude.com/docs/en/skills, read 2026-11-09; a `skillListingMaxDescChars` setting changes that cap), and for an
|
|
77
|
+
agent its `description` lines. A skill only a person can invoke is left out, since its description does not load.
|
|
78
|
+
They are measured as written, each line with its key, quoting and trailing newline, so they are an estimate of what
|
|
79
|
+
the listing holds, and a skill's can exceed a description member's own `member_bytes` when it has `when_to_use`.
|
|
80
|
+
The total leaves out a file this tool cannot read, and whatever this principle does not map, such as user-level files,
|
|
81
|
+
imports and hook output: it is what this principle's own files cost at start, not what a session starts with. The
|
|
82
|
+
files and descriptions it counts load at start whatever its activation, since the host loads them before an agent
|
|
83
|
+
reads the principle; the activation says when the agent works with the principle, and its other members load as their
|
|
84
|
+
own `when` says. Both are left out when there is nothing to list. Within the total, `files`, `file_bytes` and
|
|
85
|
+
`estimated_tokens` are left out when no file that loads whole at start could be measured, as `descriptions` is when
|
|
86
|
+
no description could; a file listed in `files_loaded` with no size loads at start uncounted.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
Asks you to assess every member of principle ID and the set as a whole. Run it after mapping, and again when
|
|
2
|
+
`show-principle` reports a member changed, unassessed, locator_lost or unavailable.
|
|
3
|
+
|
|
4
|
+
`start-audit` itself writes nothing. `submit-answer` writes the audit record, `.principles/audits/ID.json`: a full audit
|
|
5
|
+
writes it completed when its assessment has no findings or its correction is accepted. In git, commit the record each
|
|
6
|
+
time it is written, as `files_to_commit` lists it. In a full audit, make each fix after the assessment is accepted and
|
|
7
|
+
before you submit the correction that reports it, or the assessment is refused as `stale_request`, as is an edited
|
|
8
|
+
`basis`, whose `basis.last_completed_revision` names the record it follows, or null for none. The audit judges the text
|
|
9
|
+
now: a problem no completed audit recorded and fixed before `start-audit` is not recorded, and a deferred or accepted
|
|
10
|
+
finding fixed since is decided `resolved`. To record one, commit a revert, run the audit, and redo it in the correction.
|
|
11
|
+
|
|
12
|
+
It refuses with `broken_members` while any member cannot be found or read; `missing_files` groups them by file. A member
|
|
13
|
+
with a check carries `check_since_last_audit`, and `check_hidden_characters` when its check hides characters.
|
|
14
|
+
`mapped_elsewhere` shows other principles' members on its lines, judged as `mapped_elsewhere_instruction` says, with
|
|
15
|
+
`open_finding_ids` from `open_findings_elsewhere`, whose `evidence` items say `shares_lines_with`, `shares_no_lines`,
|
|
16
|
+
`whole_file` or `not_located`, or which says `evidence_not_kept`. In git, `context.uncommitted_files_outside_the_map`
|
|
17
|
+
lists up to ten files outside the map that differ from the base commit or are untracked, `not_named` counting the rest.
|
|
18
|
+
A meta-principle audit adds `package_since_last_audit`, `passage_changed` and `other_principles_with_unjudged_changes`.
|
|
19
|
+
|
|
20
|
+
## Since the last full audit
|
|
21
|
+
|
|
22
|
+
After a full audit, each member carries `carried_forward`, with its `assessed_at`, an observed one's `observed_at` (or
|
|
23
|
+
`observed_at_from_assessed_at`), `evidence_changed` and, in git, `file_changed_outside_member`, or else `judge_because`
|
|
24
|
+
with `read_the_change`, and a moved one `moved_from`; `carried_forward_instruction` and `judge_because_instruction`
|
|
25
|
+
explain them. One acknowledged with `--member` since carries `acknowledged_since_last_audit`, with that audit's
|
|
26
|
+
`last_audited_commit`, each acknowledgement and its lines then and now, or `{"omitted": "not_found_at_last_audit"}` when
|
|
27
|
+
it has moved. A new or changed check's exit status needs `review_basis`: what its review rested on, kept unverified. An
|
|
28
|
+
unchanged check also shows its `review_basis` and `review_basis_since`, a changed one `last_run_review_basis`.
|
|
29
|
+
|
|
30
|
+
## Prior findings
|
|
31
|
+
|
|
32
|
+
When the last completed audit deferred or accepted findings, `context.prior_findings` lists them, with `first_raised_at`
|
|
33
|
+
and a deferral's `waits_on` and `waits_on_since`. Decide each in `prior_finding_decisions` as `still_holds`, `resolved`,
|
|
34
|
+
`withdrawn` or `raised_again`, as `context.prior_findings_instruction` says. An older finding may claim an earlier
|
|
35
|
+
`first_raised_at` with `raised_in`, from `git log --follow -p -- .principles/audits/ID.json`. Each gives its `evidence`,
|
|
36
|
+
in git each item with `changed_since_last_audit` and `found_now`, or `evidence_not_kept` and an `evidence_request` for
|
|
37
|
+
`problem_evidence`, whose `replaces` re-points a lost item. The result names drops and re-points:
|
|
38
|
+
`prior_findings_pointers_dropped`, `prior_findings_waits_on_dropped`, `prior_findings_evidence_replaced`.
|
|
39
|
+
|
|
40
|
+
## Members to check against the activation
|
|
41
|
+
|
|
42
|
+
When the principle's activation is a set of files, `context.loads_to_check_against_activation` lists each member whose
|
|
43
|
+
file Claude Code loads at session start, with its `loads` and `listed_for`, to weigh whether a principle meant for that
|
|
44
|
+
work loads in every session; this tool compares no globs, and `not_listed_no_known_carrier` names the members this tool
|
|
45
|
+
knows no carrier for. Decide every row in `loading_decisions`, as `context.loads_to_check_instruction` explains, or this
|
|
46
|
+
tool refuses it with `incomplete_loading_decisions`. The record keeps an accepted decision as `loading_accepted`, which
|
|
47
|
+
the next audit shows as `last_accepted`, with `last_accepted.since_accepted` and whether `member_text` or `loading`
|
|
48
|
+
changed. Not listed yet: members loading on files, skills or agents, members this tool could not determine, members a
|
|
49
|
+
hook names, and anything under an invoked or always activation or in a one-member audit.
|
|
50
|
+
|
|
51
|
+
## One member's edit: `--member`
|
|
52
|
+
|
|
53
|
+
Use `--member MEMBER` when one member was edited but still says the same thing, as `list-member-problems --help`
|
|
54
|
+
describes; without it, `list-member-problems --short` reports the edit at every commit until a full audit. Its request
|
|
55
|
+
shows the `baseline_commit` it was last judged at, `member_lines` then and now (or a long member's `changed_region`,
|
|
56
|
+
`context_lines` and `from_line`, or `read_instead`), `read_the_change` and the member's `deferred_findings` and
|
|
57
|
+
`accepted_findings`, which stay; its `question` asks for `meaning_kept`. This tool checks both quotes. An id near a
|
|
58
|
+
mapped one is refused with `unknown_member`, naming the mapped one under `did_you_mean`. A one-member audit writes the
|
|
59
|
+
record once its answer is accepted, keeping the edit in the member's `acknowledgements`; commit it. It is refused with
|
|
60
|
+
`cannot_acknowledge` outside git, while an audit is open, and for a member no completed audit assessed or whose text at
|
|
61
|
+
its baseline commit does not match the audit record; until built, it is refused for a member with a check: run a full
|
|
62
|
+
audit. A member moved with `move-member` since its baseline carries `evidence_at_baseline`, and one the last full
|
|
63
|
+
audit's correction fixed carries `audit_base_commit`: judge only the change since `baseline_commit`.
|
|
64
|
+
|
|
65
|
+
## Outside git
|
|
66
|
+
|
|
67
|
+
In a project outside git, an assessment with findings writes an open record, which the accepted correction completes.
|
|
68
|
+
Until then it keeps the prior findings to list again; one opened by an older version of this tool kept none.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
Gives your answer to request REQUEST, built from that request's `response_template`. Write the JSON to a FILE outside
|
|
2
|
+
the project and pass `--file FILE`, which needs no shell quoting; `--file -` reads stdin. This tool edits none of the
|
|
3
|
+
project's files. In a full audit, make each fix after the assessment is accepted and before you submit the correction
|
|
4
|
+
that reports it: an earlier fix changes a member the request was computed from, and is refused as `stale_request`.
|
|
5
|
+
Answer each request once. If another full audit of the principle completed, or a member was acknowledged, after an
|
|
6
|
+
assessment or correction request was printed, its answer is refused as `audit_completed_since_request`, since it would
|
|
7
|
+
replace the newer record and drop what it left open: run `list-open-findings ID`, then start the audit again. Copy the
|
|
8
|
+
basis unchanged: its `last_completed_revision` says which record its request was printed after. The same answer
|
|
9
|
+
submitted again after it completed the audit writes nothing, and is accepted; an assessment whose correction completed
|
|
10
|
+
the audit is refused instead, since it would print a new correction.
|
|
11
|
+
An observed assessment may give `observed_at`, when you saw what `observation` describes, as a UTC time like
|
|
12
|
+
`2026-11-01T09:30:00Z`; none or null dates it at this audit's time. When the sighting is a dated record you read during
|
|
13
|
+
this audit, `observed_at` is the record's date, not when you read it. Another form, a time after the answer, or any on a
|
|
14
|
+
not_observed one, even null, is refused as `invalid_answer`. An `observation` judged afresh copying the last full
|
|
15
|
+
audit's word for word is refused as `observation_repeats_last_audit` unless `observed_at` is the date it names or null:
|
|
16
|
+
the date if you kept that sighting; reword a later one, null if in this audit. It checks no reworded text.
|
|
17
|
+
When this tool cannot place a piece of evidence or a `recorded_at`, such as a quote that occurs twice
|
|
18
|
+
(`ambiguous_passage`), or refuses a `check_result` (`invalid_check_result`), the refusal keeps its code, any `path`
|
|
19
|
+
and repair, starts its message with whose it is, such as "Finding F1" or "Member CLAUDE.md#Names", and gives `fields`,
|
|
20
|
+
each with its `problem` and the JSON `pointer` into your answer.
|
|
21
|
+
The correction template leaves each `action` null for you to choose: fixed, deferred, accepted or disagreed; a null or
|
|
22
|
+
unknown one is refused as `invalid_disposition`, naming the finding. A deferred disposition may give `waits_on`, one
|
|
23
|
+
line saying whom the finding waits on and to decide what, such as "<person>, to approve a CI change", which
|
|
24
|
+
`list-open-findings` prints. Null, accepted on any disposition, says it waits on no one; a line on any other action, or
|
|
25
|
+
one that spans lines, is refused as `invalid_disposition`. This tool records when it was asked; never send that time.
|
|
26
|
+
A full audit's `still_holds` decision on a prior finding may give `first_raised_at` with `raised_in`, the full sha of a
|
|
27
|
+
commit whose audit record, at `.principles/audits/ID.json` or the earlier `.memeplex/audits/ID.json`, left the same
|
|
28
|
+
finding open then, deferred or accepted, with `first_raised_at` that record's `audited_at`, to date a finding from
|
|
29
|
+
records older than the field. Give both or neither; this tool reads only that commit, and whether it is the same finding
|
|
30
|
+
is yours to judge. A claim it cannot confirm is refused, saying why and how to repair it: `raised_in_not_found`, as
|
|
31
|
+
outside git, `raised_in_unreadable`, `raised_in_lacks_finding`, `raised_in_time_differs`, or `first_raised_not_earlier`
|
|
32
|
+
when it is not earlier than the time stored.
|
|
33
|
+
A completed full audit's `open_findings` are the ids `list-open-findings` will list, its own and kept prior ones,
|
|
34
|
+
deferred or accepted; `resolved_findings`, those fixed now and prior ones decided resolved. A disagreed or withdrawn
|
|
35
|
+
finding is in neither; `prior_findings_closed` gives each prior one closed, with its decision and reason.
|
|
36
|
+
In git, `commits_since_base` lists by member id the commits since the base touching its file; an uncommitted fix shows
|
|
37
|
+
an empty list, `files_to_commit` names its file, and `commit_with`, its `-m` default replaced as
|
|
38
|
+
`commit_message_to_replace` says, commits only those, stopping during an unfinished merge. In or out of git,
|
|
39
|
+
`cited_files_missing` names each file the record cites that no longer exists, which `files_to_commit` leaves out though
|
|
40
|
+
the record still points at it. If HEAD moved but no commit touched one, `head_moved_past_base` gives `base_commit` and
|
|
41
|
+
`head`. If its fixes changed a file another principle also maps, `other_principles_with_changed_members` names each such
|
|
42
|
+
principle and its members in fixed findings' files, by `id` with the `state` `list-member-problems` gives: `changed`
|
|
43
|
+
when its text now differs from its baseline, or `locator_lost` or `unavailable` when the fix broke where this tool finds
|
|
44
|
+
it, which its `repair_with` on `show-principle ID` repairs. Then re-audit that principle, or acknowledge a member's edit
|
|
45
|
+
with `start-audit ID --member MEMBER`. A changed file no fixed finding names is not checked.
|
|
46
|
+
|
|
47
|
+
A fix changing a member's role or check with `change-member-role` or `change-member-check` lists its id, after any move,
|
|
48
|
+
in `changed_map_entries`, which only a fixed disposition may list, and may leave `changed_members` empty. A fix mapping
|
|
49
|
+
a missing member with `add-member` names it in `changed_members`. In git, this tool reads the map the audit began from
|
|
50
|
+
and refuses with `stale_map` when anything else changed, a removal too, after any `moved_members`, and
|
|
51
|
+
`claimed_change_missing` when a listed role and check are as they were; `files_to_commit` names the map. An added member
|
|
52
|
+
gets no baseline: `members_added_awaiting_assessment` names it for the next full audit. Outside git, defer the finding:
|
|
53
|
+
an entry is refused as `map_entries_need_git`, an added member as `stale_map`.
|
|
54
|
+
|
|
55
|
+
For a `start-audit --member` request, this tool checks `old_line` at the baseline commit and `new_line` now, refuses
|
|
56
|
+
with `quote_not_found` when either is not found, and prints `acknowledged` with the record in `files_to_commit`.
|
data/lib/principles/views/prompts/repoint-write-ups/point-each-moved-write-up-at-its-new-place.md
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
Each open finding in `findings` has its `recorded_at`, and what list-open-findings says of the write-up there: its
|
|
2
|
+
`write_up_opening`, or why there is none in `write_up_opening_reason`. When the file is missing, git's match for it is
|
|
3
|
+
in `write_up_opening_error.git_detected_rename`, with `starting_at_found_in_rename` when the pointer quotes a
|
|
4
|
+
`starting_at`. Git's match can pair a deleted file with an unrelated similar one, so read the file it names before you
|
|
5
|
+
use it. For each finding whose write-up you found, set its `recorded_at` in `repoints` to where the write-up is now,
|
|
6
|
+
as `{"path": ..., "heading": ...}` or with `starting_at`, and give a one-line `reason`. Leave `recorded_at` null for a
|
|
7
|
+
finding you do not repoint. Only `recorded_at` changes: the finding stays open, with its problem, action and dates,
|
|
8
|
+
for the next full audit to decide. During a full audit, give the new `recorded_at` in that finding's still_holds
|
|
9
|
+
decision instead, since a repoint changes the record that audit's request was printed after. Do not edit the audit
|
|
10
|
+
record by hand: nothing would check that the new pointer is found.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
%{count} other changed %{members} still listed from earlier commits.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
This command shows each one and what to do next:
|
data/lib/principles/views/prompts/report-the-completed-audit/replace-the-default-commit-message.md
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
The `-m` message in `commit_with`, "%{subject}", is a default: replace it with a subject in your project's own
|
|
2
|
+
convention, such as a ticket prefix, before running it, since a commit hook may refuse the default. For a message with
|
|
3
|
+
a body or trailer, write it to a file and put `-F <file>` in place of `-m` and its subject; a file needs no shell
|
|
4
|
+
quoting, and a relative path to it resolves from the project, which the command changes into first.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
These places are mapped as keeping the principles held, each with the role its member gives it:
|
|
2
|
+
|
|
3
|
+
%{members}
|
|
4
|
+
|
|
5
|
+
A place keeps them held only through what triggers it: a hook, a timer or a reader. With the user, name which of
|
|
6
|
+
the keeping steps each one lacks: running `principles list-member-problems --short` at session start, after a
|
|
7
|
+
compaction and after each commit that edits a mapped file, and acting on what it reports. The members listed in
|
|
8
|
+
members_in_entry_files are the ones in an entry file. This tool writes none of the project's guidance.
|
|
9
|
+
|
|
10
|
+
Where a step is missing, the passage is one way to add it, at %{estimated_tokens} estimated tokens in every session
|
|
11
|
+
that loads the entry file it goes in.
|
|
12
|
+
|
|
13
|
+
Once the passage is placed, map it: %{command}
|
|
14
|
+
|
|
15
|
+
To map another place that runs a missing step, giving as STEP the step it runs and as TRIGGER what starts it: %{any_place}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
Show the user the passage, which suits any entry file, and agree with them where it goes: an entry file that every
|
|
2
|
+
session of their agents loads. If a passage there already says all of it, map that one instead. If a member listed
|
|
3
|
+
in members_in_entry_files already says it, the passage is placed and mapped: go on to next_action. This tool writes
|
|
4
|
+
none of the project's guidance.
|
|
5
|
+
|
|
6
|
+
The first member need not be the passage: it can be any file or setting in the project that keeps the principles
|
|
7
|
+
in front of the agent, such as a timer of the project's own, or the committed setting that enables the plugin for
|
|
8
|
+
the team, its enabledPlugins line. Map it with a role that names, as STEP, the step it runs and, as TRIGGER, what
|
|
9
|
+
starts that step: a hook, a timer or a reader. Mapping it says only that the project names something to keep them
|
|
10
|
+
held; this principle's audit judges whether it does.
|
|
11
|
+
|
|
12
|
+
To map such a place: %{any_place}
|
|
13
|
+
|
|
14
|
+
Where the owner enables the plugin only at user scope, the project has nothing to map for it. Say so, and name the
|
|
15
|
+
two ways on: commit the project-scope enablement and map its line, or leave the "Set principles up first" line
|
|
16
|
+
standing.
|
|
17
|
+
|
|
18
|
+
Where only a reader enforces a step, with no hook or timer that runs it, say so in what you place.
|
|
19
|
+
|
|
20
|
+
Where the project says how a teammate gets `principles`, such as an install section or a setup note, link to it in
|
|
21
|
+
what you place. Say in a few words what `principles` is, so a teammate knows what the passage and any link lead to.
|
|
22
|
+
Where the project says nowhere how to get it, tell the user that a teammate who reads the passage cannot act on it
|
|
23
|
+
without that.
|
|
24
|
+
|
|
25
|
+
Where a passage the project already has carries one of the proposed passage's steps, leave that step out and map
|
|
26
|
+
that passage too, so each rule is said once, giving its file as PATH and its heading as HEADING: %{existing}
|
|
27
|
+
|
|
28
|
+
Once the passage is in the file, map it: %{command}
|
|
29
|
+
|
|
30
|
+
That command names the heading the passage is proposed under; where you placed it under another heading, give
|
|
31
|
+
--section the heading you placed it under.
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
The passage asks its steps only where `principles` is installed, so a teammate without `principles` is told to do
|
|
2
|
+
nothing it cannot, but still loads its %{estimated_tokens} estimated tokens in every session that loads the entry
|
|
3
|
+
file. Nothing runs the steps for that teammate: the plugin's session-start hook reports only in sessions where the
|
|
4
|
+
plugin is enabled, and whether a teammate's sessions have it is something this tool cannot see.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
%{findings}.%{without_waits_on}%{write_ups} %{returns} until a full audit decides %{them}.
|
|
2
|
+
%{when} list %{them}, then raise in one short message any waiting on the user or no one named. Judge by
|
|
3
|
+
context, such as git's user name, whether a named person is your user; if unsure, raise it. Do not raise any
|
|
4
|
+
waiting on someone else, or that you can see you raised in this conversation. To see whom %{each} waits on, run
|
|
5
|
+
%{command}
|
data/lib/principles/views/prompts/start-a-session/it-returns-after-each-clear-or-compaction-too.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
This line returns after each clear or compaction too
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
This line returns at each session start
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
At your next pause,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Before the user's first task,
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "json"
|
|
5
|
+
|
|
6
|
+
module Principles
|
|
7
|
+
# What this tool prints, built from domain values at print time. views/CLAUDE.md owns the boundary.
|
|
8
|
+
module Views
|
|
9
|
+
# The text this tool prints to guide the agent, kept in views/prompts/ under a folder for the
|
|
10
|
+
# workflow step that uses it. views/CLAUDE.md owns the layout. A prompt is Markdown wrapped for
|
|
11
|
+
# reading: single line breaks join into spaces, and a blank line separates paragraphs.
|
|
12
|
+
module Prompts
|
|
13
|
+
ROOT = File.join(__dir__, "prompts").freeze #: String
|
|
14
|
+
|
|
15
|
+
# A prompt's text, with each %{name} placeholder filled from values.
|
|
16
|
+
#: (String, **String) -> String
|
|
17
|
+
def self.text(name, **values) = Prompt.read(name).wrapped.filled(values)
|
|
18
|
+
|
|
19
|
+
# A prompt printed as Markdown, such as a command's --help: its lines stay as written, and each
|
|
20
|
+
# %{name} placeholder is filled from values.
|
|
21
|
+
#: (String, **String) -> String
|
|
22
|
+
def self.markdown(name, **values) = Prompt.read(name).filled(values)
|
|
23
|
+
|
|
24
|
+
# A prompt that shows a shape by example, as JSON data.
|
|
25
|
+
#: (String) -> untyped
|
|
26
|
+
def self.data(name)
|
|
27
|
+
JSON.parse(File.read(File.join(ROOT, "#{name}.json")))
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Every prompt name, relative to ROOT and without its extension.
|
|
31
|
+
#: () -> Array[String]
|
|
32
|
+
def self.names
|
|
33
|
+
Dir.glob("**/*.{md,json}", base: ROOT).map { |path| path.sub(/\.(md|json)\z/, "") }.sort
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# One packaged prompt: its name and its text as written. It lives beside Prompts, so the views' one
|
|
38
|
+
# file-reading exception stays one file; give it its own file and spec if it grows rules of its own.
|
|
39
|
+
class Prompt
|
|
40
|
+
# The prompt packaged as name.md under Prompts::ROOT.
|
|
41
|
+
#: (String) -> Prompt
|
|
42
|
+
def self.read(name) = new(name, File.read(File.join(Prompts::ROOT, "#{name}.md")).strip)
|
|
43
|
+
|
|
44
|
+
#: (String, String) -> void
|
|
45
|
+
def initialize(name, text)
|
|
46
|
+
@name = name
|
|
47
|
+
@text = text
|
|
48
|
+
freeze
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# The prompt wrapped for reading: single line breaks join into spaces, and a blank line separates
|
|
52
|
+
# paragraphs.
|
|
53
|
+
#: () -> Prompt
|
|
54
|
+
def wrapped
|
|
55
|
+
Prompt.new(@name, @text.split(/\n{2,}/).map { |paragraph| paragraph.gsub(/\s*\n\s*/, " ") }.join("\n\n"))
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# The text with each placeholder filled. Text with no values is left as it is, since a prompt may hold a
|
|
59
|
+
# literal %, but one holding a placeholder is refused, so it never reaches the agent unfilled (#422).
|
|
60
|
+
#: (Hash[Symbol, String]) -> String
|
|
61
|
+
def filled(values)
|
|
62
|
+
return format(@text, **values) unless values.empty?
|
|
63
|
+
|
|
64
|
+
placeholder = @text[/%\{\w+\}/]
|
|
65
|
+
raise ArgumentError, "prompt #{@name} needs a value for #{placeholder}" if placeholder
|
|
66
|
+
|
|
67
|
+
@text
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require_relative "invocation"
|
|
5
|
+
require_relative "prompts"
|
|
6
|
+
|
|
7
|
+
module Principles
|
|
8
|
+
# What this tool prints, from plain values a controller hands it. views/CLAUDE.md owns the boundary.
|
|
9
|
+
module Views
|
|
10
|
+
# A repoint of a principle's open findings' write-ups: its request and its result (D59).
|
|
11
|
+
class RepointResult
|
|
12
|
+
# What an accepted repoint did: the ids of the findings it repointed and of those it left where they point,
|
|
13
|
+
# and each other principle's open finding whose write-up cannot be found, with those principles (T16).
|
|
14
|
+
class Outcome
|
|
15
|
+
#: Array[String]
|
|
16
|
+
attr_reader :repointed, :unchanged
|
|
17
|
+
# Each as its principle and finding_id.
|
|
18
|
+
#: Array[Hash[String, String]]
|
|
19
|
+
attr_reader :not_found_elsewhere
|
|
20
|
+
|
|
21
|
+
#: (repointed: Array[String], unchanged: Array[String], not_found_elsewhere: Array[Hash[String, String]])
|
|
22
|
+
#| -> void
|
|
23
|
+
def initialize(repointed:, unchanged:, not_found_elsewhere:)
|
|
24
|
+
@repointed = repointed
|
|
25
|
+
@unchanged = unchanged
|
|
26
|
+
@not_found_elsewhere = not_found_elsewhere
|
|
27
|
+
freeze
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# The other principles not_found_elsewhere names, each once.
|
|
31
|
+
#: () -> Array[String]
|
|
32
|
+
def principles_elsewhere = @not_found_elsewhere.map { |finding| finding.fetch("principle") }.uniq
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
#: (Invocation) -> void
|
|
36
|
+
def initialize(invocation)
|
|
37
|
+
@invocation = invocation
|
|
38
|
+
freeze
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# findings are the open findings, each with its recorded_at and what list-open-findings says of its write-up.
|
|
42
|
+
#: (request_id: String, principle_id: String, revision: String?, findings: Array[Hash[String, untyped]])
|
|
43
|
+
#| -> Hash[String, untyped]
|
|
44
|
+
def request(request_id:, principle_id:, revision:, findings:)
|
|
45
|
+
repoints = findings.map do |finding|
|
|
46
|
+
{ "finding_id" => finding["finding_id"], "recorded_at" => nil, "reason" => "" }
|
|
47
|
+
end
|
|
48
|
+
{ "status" => "agent_judgement_required", "request_id" => request_id, "phase" => "repointing",
|
|
49
|
+
"context" => { "principle_id" => principle_id, "findings" => findings,
|
|
50
|
+
"question" => Prompts.text("repoint-write-ups/point-each-moved-write-up-at-its-new-place") },
|
|
51
|
+
"response_template" => { "request_id" => request_id, "basis" => { "revision" => revision },
|
|
52
|
+
"repoints" => repoints },
|
|
53
|
+
"answer_with" => @invocation.submit_answer(request_id) }
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# The repoints were accepted, as outcome says, and file holds them.
|
|
57
|
+
#: (principle_id: String, file: String, outcome: Outcome) -> Hash[String, untyped]
|
|
58
|
+
def repointed(principle_id:, file:, outcome:)
|
|
59
|
+
{ "status" => "write_ups_repointed", "principle_id" => principle_id, "repointed" => outcome.repointed,
|
|
60
|
+
"unchanged" => outcome.unchanged, "other_write_ups_not_found" => outcome.not_found_elsewhere,
|
|
61
|
+
"files_to_commit" => [file],
|
|
62
|
+
"next_action" => "Commit #{file}. After committing, this names no write-up of #{principle_id} it cannot " \
|
|
63
|
+
"find: #{@invocation.in_project("list-open-findings", principle_id, usage: "--short")}" \
|
|
64
|
+
"#{elsewhere(outcome.principles_elsewhere)}" }
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
private
|
|
68
|
+
|
|
69
|
+
# The request that repoints each other principle's write-ups, one per line, or nothing when there is none.
|
|
70
|
+
#: (Array[String]) -> String
|
|
71
|
+
def elsewhere(principle_ids)
|
|
72
|
+
return "" if principle_ids.empty?
|
|
73
|
+
|
|
74
|
+
commands = principle_ids.map { |id| "#{@invocation.in_project("start-audit", id, usage: "--write-ups")}\n" }
|
|
75
|
+
"\nWrite-ups of other principles cannot be found either, listed under other_write_ups_not_found. " \
|
|
76
|
+
"Check each, and repoint it with its own request:\n#{commands.join}"
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Principles
|
|
5
|
+
# What this tool prints, from plain values a controller hands it. views/CLAUDE.md owns the boundary.
|
|
6
|
+
module Views
|
|
7
|
+
# One part of a judgement request beyond its members, such as the prior findings to decide (D35) or the members
|
|
8
|
+
# to check against the activation (#355): what the agent reads of it, its list and the instruction for it, and
|
|
9
|
+
# the slots it adds to the answer's template, which the request builds in where each belongs (D60).
|
|
10
|
+
class RequestPart
|
|
11
|
+
# What the agent reads of this part: its list, then the instruction for deciding it.
|
|
12
|
+
#: Hash[String, untyped]
|
|
13
|
+
attr_reader :shown
|
|
14
|
+
# The slots this part adds to the answer's template.
|
|
15
|
+
#: Hash[String, untyped]
|
|
16
|
+
attr_reader :slots
|
|
17
|
+
|
|
18
|
+
#: (shown: Hash[String, untyped], slots: Hash[String, untyped]) -> void
|
|
19
|
+
def initialize(shown:, slots:)
|
|
20
|
+
@shown = shown
|
|
21
|
+
@slots = slots
|
|
22
|
+
freeze
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require_relative "request_part"
|
|
5
|
+
|
|
6
|
+
module Principles
|
|
7
|
+
# What this tool prints, from plain values a controller hands it. views/CLAUDE.md owns the boundary.
|
|
8
|
+
module Views
|
|
9
|
+
# A judgement request's parts beyond its members, in the order the agent reads them (D60).
|
|
10
|
+
class RequestParts
|
|
11
|
+
#: (Array[RequestPart]) -> void
|
|
12
|
+
def initialize(parts)
|
|
13
|
+
@parts = parts
|
|
14
|
+
freeze
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# entries, with what each part shows added after them, in order.
|
|
18
|
+
#: (Hash[String, untyped]) -> Hash[String, untyped]
|
|
19
|
+
def shown_after(entries) = @parts.reduce(entries) { |all, part| all.merge(part.shown) }
|
|
20
|
+
|
|
21
|
+
# template, with each part's slots added after its own entries, in order.
|
|
22
|
+
#: (Hash[String, untyped]) -> Hash[String, untyped]
|
|
23
|
+
def slotted_after(template) = @parts.reduce(template) { |all, part| all.merge(part.slots) }
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Principles
|
|
5
|
+
# What this tool prints, from plain values a controller hands it. views/CLAUDE.md owns the boundary.
|
|
6
|
+
module Views
|
|
7
|
+
# One word of a printed command, as a shell reads it: as it is when it holds only characters no shell treats
|
|
8
|
+
# specially, else in single quotes, inside which a shell expands nothing. Ids, paths and headings come from
|
|
9
|
+
# project files anyone may have written (#227).
|
|
10
|
+
class ShellWord
|
|
11
|
+
# A word every common shell reads as it is: no quote, space, $, `, glob or redirection, and no = or #,
|
|
12
|
+
# which zsh can expand.
|
|
13
|
+
PLAIN = %r{\A[\w./:@%+,-]+\z}
|
|
14
|
+
|
|
15
|
+
#: (String) -> void
|
|
16
|
+
def initialize(value)
|
|
17
|
+
@value = value
|
|
18
|
+
freeze
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
#: () -> String
|
|
22
|
+
def to_s
|
|
23
|
+
return @value if PLAIN.match?(@value)
|
|
24
|
+
|
|
25
|
+
"'#{@value.gsub("'") { "'\\''" }}'"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Principles
|
|
5
|
+
# What this tool prints, from plain values a controller hands it. views/CLAUDE.md owns the boundary.
|
|
6
|
+
module Views
|
|
7
|
+
# Text from a project file or an agent's answer, printed outside JSON with each control, format and separator
|
|
8
|
+
# character written as \uXXXX, as JSON output shows it, so a tab cannot split a field and an invisible character
|
|
9
|
+
# cannot hide (#227). cli.rb escapes printed JSON without control characters, since JSON already escapes them
|
|
10
|
+
# inside strings and its own newlines must stay; so the two are not one rule to fold together.
|
|
11
|
+
class VisibleText
|
|
12
|
+
#: (String) -> void
|
|
13
|
+
def initialize(text)
|
|
14
|
+
@text = text
|
|
15
|
+
freeze
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
#: () -> String
|
|
19
|
+
def to_s
|
|
20
|
+
@text.gsub(/[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]/) do |character|
|
|
21
|
+
character.encode("UTF-16BE").unpack("n*").map { |unit| format("\\u%04x", unit) }.join
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|