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,170 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require_relative "invocation"
|
|
5
|
+
require_relative "meta_principle_passage"
|
|
6
|
+
require_relative "printed_principle"
|
|
7
|
+
|
|
8
|
+
module Principles
|
|
9
|
+
# What this tool prints, from plain values a controller hands it. views/CLAUDE.md owns the boundary.
|
|
10
|
+
module Views
|
|
11
|
+
# What show-meta-principle-passage prints: the map its printed add-member writes, the facts of the project's entry
|
|
12
|
+
# files, the one passage any of them would take, and the commands that map the passage once the agent has placed
|
|
13
|
+
# it with the user (D68, D71, D74).
|
|
14
|
+
class MetaPrincipleResult
|
|
15
|
+
# How the printed add-member commands map the passage: heading is the passage's heading, which they name as
|
|
16
|
+
# its member's section, beside role, the role they give that member; step_role is the role they give a
|
|
17
|
+
# passage the project has that carries one of the passage's steps, and place_role the one they give any other
|
|
18
|
+
# place that keeps the principles held, such as a timer or a settings line (D75).
|
|
19
|
+
class PassageMapping
|
|
20
|
+
#: String
|
|
21
|
+
attr_reader :heading, :role, :step_role, :place_role
|
|
22
|
+
|
|
23
|
+
#: (heading: String, role: String, step_role: String, place_role: String) -> void
|
|
24
|
+
def initialize(heading:, role:, step_role:, place_role:)
|
|
25
|
+
@heading = heading
|
|
26
|
+
@role = role
|
|
27
|
+
@step_role = step_role
|
|
28
|
+
@place_role = place_role
|
|
29
|
+
freeze
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# mapping is how the printed commands map the passage; in_git says whether a commit can be the member's
|
|
34
|
+
# baseline.
|
|
35
|
+
#: (Invocation, PassageMapping, in_git: bool) -> void
|
|
36
|
+
def initialize(invocation, mapping, in_git:)
|
|
37
|
+
@invocation = invocation
|
|
38
|
+
@mapping = mapping
|
|
39
|
+
@in_git = in_git
|
|
40
|
+
freeze
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# The passage, as the agent pastes it into an entry file, its lines kept.
|
|
44
|
+
#: () -> String
|
|
45
|
+
def passage = MetaPrinciplePassage.new(heading: @mapping.heading).text
|
|
46
|
+
|
|
47
|
+
# What the passage presumes of a teammate without principles, given its estimated size.
|
|
48
|
+
#: (Integer) -> String
|
|
49
|
+
def presumes(estimated_tokens)
|
|
50
|
+
Prompts.text("set-principles-up/what-the-passage-presumes", estimated_tokens: estimated_tokens.to_s)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Where the passage can go, as the agent places it from: how this run was started and whether the plugin's
|
|
54
|
+
# session-start hook runs in this session, each root entry file's facts, and the passage's text with its size
|
|
55
|
+
# and what it presumes of a teammate without principles.
|
|
56
|
+
class Placement
|
|
57
|
+
#: (runs_from: String, session_start_hook_in_this_session: bool, entry_files: Array[Hash[String, untyped]],
|
|
58
|
+
#| passage: Hash[String, untyped]) -> void
|
|
59
|
+
def initialize(runs_from:, session_start_hook_in_this_session:, entry_files:, passage:)
|
|
60
|
+
@fields = { "runs_from" => runs_from,
|
|
61
|
+
"session_start_hook_in_this_session" => session_start_hook_in_this_session,
|
|
62
|
+
"entry_files" => entry_files, "passage" => passage }.freeze #: Hash[String, untyped]
|
|
63
|
+
freeze
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
#: () -> Hash[String, untyped]
|
|
67
|
+
def to_h = @fields
|
|
68
|
+
|
|
69
|
+
# The passage's estimated size, which loads in every session that loads the entry file it goes in.
|
|
70
|
+
#: () -> Integer
|
|
71
|
+
def estimated_tokens = @fields.fetch("passage").fetch("estimated_tokens")
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# The map as the project holds it: already_mapped says the map was there before this run, and
|
|
75
|
+
# members_in_entry_files names its members already in an entry file, by id and path; set_up says the map has a
|
|
76
|
+
# member, so the question asks which keeping step each lacks in place of asking to place the passage (D75).
|
|
77
|
+
class MapInProject
|
|
78
|
+
#: bool
|
|
79
|
+
attr_reader :set_up
|
|
80
|
+
|
|
81
|
+
#: (already_mapped: bool, members_in_entry_files: Array[Hash[String, String]], set_up: bool) -> void
|
|
82
|
+
def initialize(already_mapped:, members_in_entry_files:, set_up:)
|
|
83
|
+
@fields = { "already_mapped" => already_mapped,
|
|
84
|
+
"members_in_entry_files" => members_in_entry_files }.freeze #: Hash[String, untyped]
|
|
85
|
+
@set_up = set_up
|
|
86
|
+
freeze
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
#: () -> Hash[String, untyped]
|
|
90
|
+
def to_h = @fields
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# existing_principles lists the project's other principles as list-principles lists them.
|
|
94
|
+
#: (PrintedPrinciple, Placement, MapInProject, existing_principles: Array[Hash[String, untyped]])
|
|
95
|
+
#| -> Hash[String, untyped]
|
|
96
|
+
def proposal(principle, placement, map_in_project, existing_principles:)
|
|
97
|
+
{ "status" => "question", "principle_id" => principle.id, "map_file" => principle.file,
|
|
98
|
+
"map" => principle.map, **map_in_project.to_h, **placement.to_h,
|
|
99
|
+
"existing_principles" => existing_principles,
|
|
100
|
+
"question" => map_in_project.set_up ? steps_lacking(principle, placement) : question(principle.id),
|
|
101
|
+
"answer_with" => add_member(principle.id), "next_action" => next_action(principle.id, existing_principles) }
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
private
|
|
105
|
+
|
|
106
|
+
# What to agree with the user and place, with the command that maps a passage the project has in a step's
|
|
107
|
+
# place, and the one that maps the passage once it is placed.
|
|
108
|
+
#: (String) -> String
|
|
109
|
+
def question(id)
|
|
110
|
+
Prompts.text("set-principles-up/place-the-passage-with-the-user",
|
|
111
|
+
command: add_member(id), existing: add_existing(id), any_place: add_place(id))
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Each mapped member's place and role, and which keeping step each lacks, with the passage as one way to add a
|
|
115
|
+
# missing step, at its size, and the command that maps another place.
|
|
116
|
+
#: (PrintedPrinciple, Placement) -> String
|
|
117
|
+
def steps_lacking(principle, placement)
|
|
118
|
+
members = principle.members.map { |member| "- #{member.fetch("id")}: #{member.fetch("role")}" }.join("\n")
|
|
119
|
+
Prompts.text("set-principles-up/name-the-step-each-member-lacks",
|
|
120
|
+
members: members, command: add_member(principle.id), any_place: add_place(principle.id),
|
|
121
|
+
estimated_tokens: placement.estimated_tokens.to_s)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# The add-member that maps any other place that keeps the principles held, by its path and a role naming the
|
|
125
|
+
# step it runs and what starts it.
|
|
126
|
+
#: (String) -> String
|
|
127
|
+
def add_place(id)
|
|
128
|
+
@invocation.in_project("add-member", id, usage: "PATH --role \"#{@mapping.place_role}\"")
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# The add-member that maps a passage the project already has, which carries one of the passage's steps.
|
|
132
|
+
#: (String) -> String
|
|
133
|
+
def add_existing(id)
|
|
134
|
+
@invocation.in_project("add-member", id, usage: "PATH --section \"HEADING\" --role \"#{@mapping.step_role}\"")
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
#: (String) -> String
|
|
138
|
+
def add_member(id)
|
|
139
|
+
@invocation.in_project("add-member", id,
|
|
140
|
+
usage: "ENTRY_FILE --section \"#{@mapping.heading}\" --role \"#{@mapping.role}\"")
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# What follows placing the passage: committing it, which outside git is not the member's baseline, and the
|
|
144
|
+
# first full audit, which waits until the project has a principle of its own to keep held.
|
|
145
|
+
#: (String, Array[Hash[String, untyped]]) -> String
|
|
146
|
+
def next_action(id, existing_principles)
|
|
147
|
+
baseline = if @in_git
|
|
148
|
+
"Then commit .principles/ and the entry file you changed."
|
|
149
|
+
else
|
|
150
|
+
"This principle's first full audit gives the passage's member its baseline, since this project " \
|
|
151
|
+
"is not in git."
|
|
152
|
+
end
|
|
153
|
+
[baseline, first_audit(id, existing_principles)].join(" ")
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
#: (String, Array[Hash[String, untyped]]) -> String
|
|
157
|
+
def first_audit(id, existing_principles)
|
|
158
|
+
if existing_principles.empty?
|
|
159
|
+
return "This principle's first full audit judges whether the keeping works, so leave it until one of the " \
|
|
160
|
+
"project's own principles is mapped.\n" \
|
|
161
|
+
"To find the first of them: #{@invocation.in_project("list-candidate-files")}"
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
"This principle's first full audit judges whether the keeping works for the principles under " \
|
|
165
|
+
"existing_principles.\n" \
|
|
166
|
+
"To start it: #{@invocation.in_project("start-audit", id)}"
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require_relative "prompts"
|
|
5
|
+
require_relative "request_part"
|
|
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
|
+
# How a full audit shows the findings other principles leave open on members sharing its members' lines: each
|
|
11
|
+
# once, which mapped_elsewhere names by id, with what to do with them (#772, D62).
|
|
12
|
+
class OpenFindingsElsewhereResult
|
|
13
|
+
# findings are each such finding, with its principle, id, problem and action.
|
|
14
|
+
#: (Array[Hash[String, untyped]]) -> void
|
|
15
|
+
def initialize(findings)
|
|
16
|
+
@findings = findings
|
|
17
|
+
freeze
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# The assessment request's part that lists them and says what to do with them; nil when there are none. It adds
|
|
21
|
+
# nothing to the template: a finding here is decided in its own principle's audit.
|
|
22
|
+
#: () -> RequestPart?
|
|
23
|
+
def part
|
|
24
|
+
return if @findings.empty?
|
|
25
|
+
|
|
26
|
+
instruction = Prompts.text("assess-every-member/name-another-principles-open-finding-rather-than-raise-it")
|
|
27
|
+
RequestPart.new(shown: { "open_findings_elsewhere" => @findings,
|
|
28
|
+
"open_findings_elsewhere_instruction" => instruction }, slots: {})
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require_relative "invocation"
|
|
5
|
+
require_relative "problem_lines"
|
|
6
|
+
require_relative "visible_text"
|
|
7
|
+
require_relative "prompts"
|
|
8
|
+
|
|
9
|
+
module Principles
|
|
10
|
+
# What this tool prints, from plain values a controller hands it. views/CLAUDE.md owns the boundary.
|
|
11
|
+
module Views
|
|
12
|
+
# list-open-findings --short: the one line a session-start hook puts into the agent's context while any
|
|
13
|
+
# finding is open, and nothing when none is (D47). It says how many wait, how long the oldest has, what that
|
|
14
|
+
# one waits on, and the command that lists them all, worded as something to act on.
|
|
15
|
+
class OpenFindingsLine
|
|
16
|
+
# A waits_on longer than this is cut, so the line stays one short line.
|
|
17
|
+
WAITS_ON_LIMIT = 80
|
|
18
|
+
|
|
19
|
+
#: (Invocation) -> void
|
|
20
|
+
def initialize(invocation)
|
|
21
|
+
@invocation = invocation
|
|
22
|
+
freeze
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# waiting is nil when no finding is open, or the count of open findings with the oldest one's principle,
|
|
26
|
+
# finding_id, days_open and, when it says, waits_on. not_found is each open finding, by principle and
|
|
27
|
+
# finding_id, whose write-up can no longer be found where its recorded_at points (#694). source is the
|
|
28
|
+
# session's start: startup, clear or compact.
|
|
29
|
+
#: (Hash[String, untyped]?, ?Array[Hash[String, untyped]], ?source: String) -> Lines
|
|
30
|
+
def short(waiting, not_found = [], source: "startup")
|
|
31
|
+
Lines.new(stdout: waiting ? "#{line(waiting, not_found, source)}\n" : "", stderr: "", status: 0)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
#: (Hash[String, untyped], Array[Hash[String, untyped]], String) -> String
|
|
37
|
+
def line(waiting, not_found, source)
|
|
38
|
+
count = waiting.fetch("count")
|
|
39
|
+
them, each = pronouns(count)
|
|
40
|
+
Prompts.text("start-a-session/act-on-the-open-findings",
|
|
41
|
+
when: raise_when(source), returns: returns(source),
|
|
42
|
+
findings: "#{counted(count)}#{waited(waiting)} (#{named(waiting)})",
|
|
43
|
+
without_waits_on: without_waits_on(count, waiting.fetch("without_waits_on", 0)),
|
|
44
|
+
write_ups: write_ups(not_found),
|
|
45
|
+
them: them, each: each, command: @invocation.in_project("list-open-findings"))
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# When to raise the findings: before the user's first task at startup, and at the next pause once the session is
|
|
49
|
+
# under way, after /clear or a compaction (#717).
|
|
50
|
+
#: (String) -> String
|
|
51
|
+
def raise_when(source)
|
|
52
|
+
return Prompts.text("start-a-session/raise-them-before-the-first-task") if source == "startup"
|
|
53
|
+
|
|
54
|
+
Prompts.text("start-a-session/raise-them-at-the-next-pause")
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# When the line comes back: at each session start, and after each clear or compaction too (#741).
|
|
58
|
+
#: (String) -> String
|
|
59
|
+
def returns(source)
|
|
60
|
+
return Prompts.text("start-a-session/it-returns-at-each-session-start") if source == "startup"
|
|
61
|
+
|
|
62
|
+
Prompts.text("start-a-session/it-returns-after-each-clear-or-compaction-too")
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# How many of several open findings record no waits_on, since the line names only the oldest's (#736). One
|
|
66
|
+
# open finding's own name already shows whether it does, so its line says nothing more.
|
|
67
|
+
#: (Integer, Integer) -> String
|
|
68
|
+
def without_waits_on(count, without)
|
|
69
|
+
return "" if count == 1 || without.zero?
|
|
70
|
+
return " All #{count} have no waits_on." if without == count
|
|
71
|
+
|
|
72
|
+
" #{without} #{without == 1 ? "has" : "have"} no waits_on."
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# The words the line refers to the findings by, all of them and each one, singular or plural together.
|
|
76
|
+
#: (Integer) -> [String, String]
|
|
77
|
+
def pronouns(count)
|
|
78
|
+
count == 1 ? %w[it it] : %w[them each]
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# The sentence naming the write-ups that can no longer be found, the first by its principle and id, or
|
|
82
|
+
# nothing when every pointer resolves, so the usual line is unchanged.
|
|
83
|
+
#: (Array[Hash[String, untyped]]) -> String
|
|
84
|
+
def write_ups(not_found)
|
|
85
|
+
first = not_found.first or return ""
|
|
86
|
+
named = "#{first.fetch("principle")} #{VisibleText.new(first.fetch("finding_id"))}"
|
|
87
|
+
return " The write-up of #{named} cannot be found where its recorded_at points, and the list says why." \
|
|
88
|
+
if not_found.one?
|
|
89
|
+
|
|
90
|
+
" The write-ups of #{not_found.length} findings, the first #{named}, cannot be found where their " \
|
|
91
|
+
"recorded_at points, and the list says why."
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
#: (Integer) -> String
|
|
95
|
+
def counted(count)
|
|
96
|
+
count == 1 ? "1 audit finding is still open, " : "#{count} audit findings are still open, the oldest "
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
#: (Hash[String, untyped]) -> String
|
|
100
|
+
def waited(waiting)
|
|
101
|
+
days = waiting.fetch("days_open")
|
|
102
|
+
return "for less than a day" if days < 1
|
|
103
|
+
|
|
104
|
+
"for #{days} #{days == 1 ? "day" : "days"}"
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# The oldest finding's principle and id, and what it waits on, cut when long. The id and waits_on are free
|
|
108
|
+
# text, so each is cut by characters first and then escaped, which may run past the limit to show them (#227).
|
|
109
|
+
#: (Hash[String, untyped]) -> String
|
|
110
|
+
def named(waiting)
|
|
111
|
+
named = "#{waiting.fetch("principle")} #{VisibleText.new(waiting.fetch("finding_id"))}"
|
|
112
|
+
waits_on = waiting["waits_on"] or return named
|
|
113
|
+
waits_on = closed("#{waits_on[0, WAITS_ON_LIMIT - 3]}...") if waits_on.length > WAITS_ON_LIMIT
|
|
114
|
+
"#{named}, waits on: #{VisibleText.new(waits_on)}"
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# A cut waits_on with a ")" for each "(" the cut left open, so the line's own parenthesis still reads as
|
|
118
|
+
# closing the finding's name (#685).
|
|
119
|
+
#: (String) -> String
|
|
120
|
+
def closed(cut)
|
|
121
|
+
cut + (")" * [cut.count("(") - cut.count(")"), 0].max)
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require_relative "principle_with_changed_members"
|
|
5
|
+
require_relative "prompts"
|
|
6
|
+
require_relative "request_part"
|
|
7
|
+
|
|
8
|
+
module Principles
|
|
9
|
+
# What this tool prints, from plain values a controller hands it. views/CLAUDE.md owns the boundary.
|
|
10
|
+
module Views
|
|
11
|
+
# How the meta-principle's full audit states, as a fact, each other principle with members no audit has judged
|
|
12
|
+
# as they are now, which a check on its passage once reported, beside the release since its last audit (D71).
|
|
13
|
+
class OtherPrinciplesUnjudgedResult
|
|
14
|
+
# principles holds each other principle with such members, by id with their states; empty when there are none.
|
|
15
|
+
#: (Array[PrincipleWithChangedMembers]) -> void
|
|
16
|
+
def initialize(principles)
|
|
17
|
+
@principles = principles
|
|
18
|
+
freeze
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# The request's part listing them under principles, with why, how to weigh them, as the release part beside it
|
|
22
|
+
# gives its own.
|
|
23
|
+
#: () -> RequestPart
|
|
24
|
+
def part
|
|
25
|
+
why = Prompts.text("assess-every-member/judge-the-keeping-against-the-other-principles")
|
|
26
|
+
RequestPart.new(shown: { "other_principles_with_unjudged_changes" => { "principles" => @principles.map(&:to_h),
|
|
27
|
+
"why" => why } },
|
|
28
|
+
slots: {})
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require_relative "prompts"
|
|
5
|
+
require_relative "request_part"
|
|
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
|
+
# How a full audit's request names the files outside the map that differ from the base commit, which a check and
|
|
11
|
+
# the answer's evidence read as they are now (#409, #426).
|
|
12
|
+
class OutsideTheMapResult
|
|
13
|
+
# outside names the files outside, as paths and any count not_named; nil when there are none or no base commit.
|
|
14
|
+
#: (Hash[String, untyped]?) -> void
|
|
15
|
+
def initialize(outside)
|
|
16
|
+
@outside = outside
|
|
17
|
+
freeze
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# The request's part naming the files outside, with why they matter to the answer; nil when there are none,
|
|
21
|
+
# and then nothing is printed.
|
|
22
|
+
#: () -> RequestPart?
|
|
23
|
+
def part
|
|
24
|
+
outside = @outside or return
|
|
25
|
+
|
|
26
|
+
why = Prompts.text("assess-every-member/uncommitted-files-outside-the-map")
|
|
27
|
+
RequestPart.new(shown: { "uncommitted_files_outside_the_map" => outside.merge("why" => why) }, slots: {})
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require_relative "invocation"
|
|
5
|
+
require_relative "prompts"
|
|
6
|
+
require_relative "request_part"
|
|
7
|
+
|
|
8
|
+
module Principles
|
|
9
|
+
# What this tool prints, from plain values a controller hands it. views/CLAUDE.md owns the boundary.
|
|
10
|
+
module Views
|
|
11
|
+
# How the meta-principle's full audit states the release of principles its last completed audit ran under beside
|
|
12
|
+
# the one running now, as facts for the agent to judge (D68).
|
|
13
|
+
class PackageSinceLastAuditResult
|
|
14
|
+
# at_last_audit is the version the last completed audit ran under, or nil when none recorded one; now is the
|
|
15
|
+
# version running now; passage_changed says whether the passage setup proposes changed since, or is nil with
|
|
16
|
+
# nothing to compare. invocation names the setup command the instruction prints.
|
|
17
|
+
#: (Invocation, at_last_audit: String?, now: String, passage_changed: bool?) -> void
|
|
18
|
+
def initialize(invocation, at_last_audit:, now:, passage_changed:)
|
|
19
|
+
@invocation = invocation
|
|
20
|
+
@since = { "version_at_last_audit" => at_last_audit, "version_now" => now,
|
|
21
|
+
"passage_changed" => passage_changed }.freeze #: Hash[String, untyped]
|
|
22
|
+
freeze
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# The request's part stating the release since the last audit, with what to do about a change.
|
|
26
|
+
#: () -> RequestPart
|
|
27
|
+
def part
|
|
28
|
+
why = Prompts.text("assess-every-member/judge-the-keeping-under-the-release-since-the-last-audit",
|
|
29
|
+
setup: @invocation.in_project("show-meta-principle-passage"))
|
|
30
|
+
RequestPart.new(shown: { "package_since_last_audit" => @since.merge("why" => why) }, slots: {})
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require_relative "invocation"
|
|
5
|
+
require_relative "printed_principle"
|
|
6
|
+
require_relative "member_repairs"
|
|
7
|
+
require_relative "prompts"
|
|
8
|
+
|
|
9
|
+
module Principles
|
|
10
|
+
# What this tool prints, from plain values a controller hands it. views/CLAUDE.md owns the boundary.
|
|
11
|
+
module Views
|
|
12
|
+
# The JSON results of reading principles, show-principle and list-principles, with commands for the invocation
|
|
13
|
+
# running now. They change with what a read reports, such as freshness and repairs; MapResult prints the writes.
|
|
14
|
+
class PrincipleReadResult
|
|
15
|
+
#: (Invocation) -> void
|
|
16
|
+
def initialize(invocation)
|
|
17
|
+
@invocation = invocation
|
|
18
|
+
freeze
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# show-principle: each member with where its text is now and its freshness, and each member in broken, the ids
|
|
22
|
+
# of those an audit would refuse, with its repair_with commands (#272).
|
|
23
|
+
# hook_settings_not_read names each project settings file whose hooks this tool could not read (#491).
|
|
24
|
+
# loaded_files lists each file the members load once, with the total of those loading at session start (#483).
|
|
25
|
+
#: (PrintedPrinciple, broken: Array[String], ?hook_settings_not_read: Array[Hash[String, String]],
|
|
26
|
+
#| ?loaded_files: Hash[String, untyped]) -> Hash[String, untyped]
|
|
27
|
+
def shown(principle, broken:, hook_settings_not_read: [], loaded_files: {})
|
|
28
|
+
unread = hook_settings_not_read.empty? ? {} : { "hook_settings_not_read" => hook_settings_not_read }
|
|
29
|
+
{ "id" => principle.id, "map_file" => principle.file, **principle.declared,
|
|
30
|
+
"members" => principle.members.map { |member| repaired(principle.id, member, broken) },
|
|
31
|
+
**loaded_files, **unread, "next_action" => shown_next_action(principle, broken) }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# list-principles: each entry is { "id", "description", "members_by_freshness" }. Until principles is set_up,
|
|
35
|
+
# its next_action puts setting it up first.
|
|
36
|
+
#: (Array[Hash[String, untyped]], set_up: bool) -> Hash[String, untyped]
|
|
37
|
+
def listing(entries, set_up:)
|
|
38
|
+
next_action = if entries.empty?
|
|
39
|
+
"To map one, start with: #{@invocation.in_project("list-candidate-files")}"
|
|
40
|
+
else
|
|
41
|
+
"To see a principle's members: #{@invocation.in_project("show-principle", usage: "ID")}\n" \
|
|
42
|
+
"To audit it: #{@invocation.in_project("start-audit", usage: "ID")}"
|
|
43
|
+
end
|
|
44
|
+
first = set_up ? [] : [set_up_first]
|
|
45
|
+
{ "principles" => entries, "next_action" => [*first, next_action].join("\n") }
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# list-principles' note on the meta-principle's map, kept in file, when it has no members, with the two ways on
|
|
49
|
+
# (#931).
|
|
50
|
+
#: (String) -> Hash[String, String]
|
|
51
|
+
def no_members(file)
|
|
52
|
+
setup = @invocation.in_project("show-meta-principle-passage")
|
|
53
|
+
{ "no_members" => "This map has no members, as a setup that wrote it before its first member, or removing " \
|
|
54
|
+
"its last member, leaves it. Either remove #{file} and commit the removal, or add its " \
|
|
55
|
+
"first member with the add-member this prints: #{setup}" }
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
private
|
|
59
|
+
|
|
60
|
+
# The line that puts setting principles up first, ending in its command.
|
|
61
|
+
#: () -> String
|
|
62
|
+
def set_up_first
|
|
63
|
+
Prompts.text("set-principles-up/set-up-first",
|
|
64
|
+
command: @invocation.in_project("show-meta-principle-passage"))
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# member, with its repairs when broken names it.
|
|
68
|
+
#: (String, Hash[String, untyped], Array[String]) -> Hash[String, untyped]
|
|
69
|
+
def repaired(id, member, broken)
|
|
70
|
+
MemberRepairs.new(@invocation).beside(id, member, broken: broken.include?(member.fetch("id")))
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Repair each member in broken, the ids of those an audit would refuse; otherwise audit when one changed or was
|
|
74
|
+
# never assessed.
|
|
75
|
+
#: (PrintedPrinciple, Array[String]) -> String
|
|
76
|
+
def shown_next_action(principle, broken)
|
|
77
|
+
unless broken.empty?
|
|
78
|
+
return "Repair each member that cannot be found or read before auditing, with one of the commands in " \
|
|
79
|
+
"its repair_with: #{broken.join(", ")}."
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
"Audit when a member is changed or unassessed: #{@invocation.in_project("start-audit", principle.id)}"
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
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 other principle whose members a completed audit's fixes changed or broke, as its result names it under
|
|
8
|
+
# other_principles_with_changed_members, to re-audit by its id (#410, #823).
|
|
9
|
+
class PrincipleWithChangedMembers
|
|
10
|
+
#: (principle_id: String, members: Array[Hash[String, untyped]]) -> void
|
|
11
|
+
def initialize(principle_id:, members:)
|
|
12
|
+
@principle_id = principle_id
|
|
13
|
+
@members = members
|
|
14
|
+
freeze
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# The principle to re-audit.
|
|
18
|
+
#: String
|
|
19
|
+
attr_reader :principle_id
|
|
20
|
+
|
|
21
|
+
# The fields as printed: the principle's id and each changed or broken member, by id with its state.
|
|
22
|
+
#: () -> Hash[String, untyped]
|
|
23
|
+
def to_h = { "principle_id" => @principle_id, "members" => @members }
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require_relative "../prose_list"
|
|
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
|
+
# The principles no full audit has completed, as list-member-problems' next_action names them in one line, then
|
|
10
|
+
# each one's audit to start on a line of its own, filled and shell-quoted so the agent types no id (D58, #731,
|
|
11
|
+
# #755).
|
|
12
|
+
class PrinciplesWithNoCompletedAudit
|
|
13
|
+
# audits holds each principle's start-audit command, in the order of ids.
|
|
14
|
+
#: (ids: Array[String], audits: Array[String]) -> void
|
|
15
|
+
def initialize(ids:, audits:)
|
|
16
|
+
@ids = ids
|
|
17
|
+
@audits = audits
|
|
18
|
+
freeze
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
#: () -> String
|
|
22
|
+
def to_s
|
|
23
|
+
one = @ids.length == 1
|
|
24
|
+
carry = one ? "its members carry it" : "their members carry them"
|
|
25
|
+
"No full audit has completed for #{ProseList.new(@ids)}, so whether #{carry} is unknown. " \
|
|
26
|
+
"To start #{one ? "one" : "each"}:\n#{@audits.join("\n")}"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
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
|
+
# A principle as printed: its id, map file, description and members. Each member is a plain hash that
|
|
8
|
+
# already carries its "id", and on show-principle its snapshot and freshness too.
|
|
9
|
+
class PrintedPrinciple
|
|
10
|
+
#: String
|
|
11
|
+
attr_reader :id
|
|
12
|
+
#: String
|
|
13
|
+
attr_reader :file
|
|
14
|
+
#: String?
|
|
15
|
+
attr_reader :description
|
|
16
|
+
#: Array[Hash[String, untyped]]
|
|
17
|
+
attr_reader :members
|
|
18
|
+
#: Hash[String, untyped]?
|
|
19
|
+
attr_reader :activation
|
|
20
|
+
|
|
21
|
+
# activation is when the agent said the principle's work is in hand, or nil when it has not said (D38).
|
|
22
|
+
#: (id: String, file: String, description: String?, members: Array[Hash[String, untyped]],
|
|
23
|
+
#| ?activation: Hash[String, untyped]?) -> void
|
|
24
|
+
def initialize(id:, file:, description:, members:, activation: nil)
|
|
25
|
+
@id = id
|
|
26
|
+
@file = file
|
|
27
|
+
@description = description
|
|
28
|
+
@members = members.freeze #: Array[Hash[String, untyped]]
|
|
29
|
+
@activation = activation #: Hash[String, untyped]?
|
|
30
|
+
freeze
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# What the principle declares as a whole: its description, and its activation once the agent has said it.
|
|
34
|
+
#: () -> Hash[String, untyped]
|
|
35
|
+
def declared
|
|
36
|
+
{ "description" => @description, **({ "activation" => @activation } if @activation) }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
#: () -> Hash[String, untyped]
|
|
40
|
+
def map
|
|
41
|
+
{ **declared, "members" => @members }
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
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
|
+
# How a completed full audit's result says what it decided about each prior finding (D35).
|
|
8
|
+
class PriorFindingDecisionsResult
|
|
9
|
+
# kept_ids are the prior findings it kept and closed those it closed; dropped is any pointer a kept one's
|
|
10
|
+
# decision dropped (#374), waits_on_dropped any waits_on it dropped, with null or by accepting it (D52), and
|
|
11
|
+
# evidence_replaced each kept evidence item a decision gave a new place, as it was and is now (D70).
|
|
12
|
+
#: (kept_ids: Array[String], closed: Array[Hash[String, untyped]], dropped: Array[Hash[String, untyped]],
|
|
13
|
+
#| waits_on_dropped: Array[Hash[String, untyped]], evidence_replaced: Array[Hash[String, untyped]]) -> void
|
|
14
|
+
def initialize(kept_ids:, closed:, dropped:, waits_on_dropped:, evidence_replaced:)
|
|
15
|
+
@kept_ids = kept_ids
|
|
16
|
+
@closed = closed
|
|
17
|
+
@dropped = dropped
|
|
18
|
+
@waits_on_dropped = waits_on_dropped
|
|
19
|
+
@evidence_replaced = evidence_replaced
|
|
20
|
+
freeze
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# output, with these decisions added; unchanged when there were no prior findings to decide.
|
|
24
|
+
#: (Hash[String, untyped]) -> Hash[String, untyped]
|
|
25
|
+
def added_to(output)
|
|
26
|
+
return output if @kept_ids.empty? && @closed.empty?
|
|
27
|
+
|
|
28
|
+
decided = output.merge("prior_findings_kept" => @kept_ids, "prior_findings_closed" => @closed)
|
|
29
|
+
decided = decided.merge("prior_findings_pointers_dropped" => @dropped) unless @dropped.empty?
|
|
30
|
+
decided = decided.merge("prior_findings_waits_on_dropped" => @waits_on_dropped) unless @waits_on_dropped.empty?
|
|
31
|
+
@evidence_replaced.empty? ? decided : decided.merge("prior_findings_evidence_replaced" => @evidence_replaced)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|