fensu-cli 0.2.1__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/Cargo.lock +6 -1
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/Cargo.toml +3 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/PKG-INFO +4 -4
- fensu_cli-0.3.0/README.md +5 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-cli/Cargo.toml +8 -2
- fensu_cli-0.3.0/crates/fensu-cli/assets/skills_invariant.json +1 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/command/constants.rs +19 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/command/helpers/map_parsing.rs +184 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/command/helpers/memory_execution.rs +254 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/command/helpers/memory_graph_rendering.rs +107 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/command/helpers/memory_help.rs +33 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/command/helpers/memory_human_rendering.rs +296 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/command/helpers/memory_parsing.rs +400 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/command/helpers/memory_structured_rendering.rs +130 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/command/helpers/memory_values.rs +117 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/command/helpers/mod.rs +8 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/command/main/help.rs +3 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/command/main/map.rs +11 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/command/main/memory.rs +6 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-cli/src/command/main/mod.rs +3 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-cli/src/command/main/run_cli.rs +15 -7
- fensu_cli-0.3.0/crates/fensu-cli/src/command/main/skills.rs +5 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/command/mod.rs +4 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/command/models.rs +47 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/configuration/helpers/discovery.rs +22 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/configuration/helpers/exceptions.rs +128 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/configuration/helpers/loading.rs +42 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/configuration/helpers/mod.rs +5 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/configuration/helpers/parsing.rs +234 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/configuration/helpers/validation.rs +305 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/configuration/main/custom_rules.rs +7 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/configuration/main/load.rs +8 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/configuration/main/load_optional.rs +8 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/configuration/main/mod.rs +3 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/configuration/mod.rs +2 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/constants.rs +51 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-cli/src/helpers/check_evaluation.rs +9 -3
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-cli/src/helpers/check_execution.rs +7 -3
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-cli/src/helpers/check_policy.rs +58 -3
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-cli/src/helpers/check_project.rs +29 -8
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-cli/src/helpers/init.rs +17 -17
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-cli/src/helpers/mod.rs +0 -1
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-cli/src/helpers/process.rs +41 -5
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-cli/src/helpers/rule.rs +25 -5
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-cli/src/lib.rs +3 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/mapping/constants.rs +10 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/mapping/helpers/cache.rs +224 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/mapping/helpers/decoding.rs +88 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/mapping/helpers/execution.rs +98 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/mapping/helpers/identity.rs +11 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/mapping/helpers/index.rs +367 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/mapping/helpers/mod.rs +8 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/mapping/helpers/project.rs +301 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/mapping/helpers/render.rs +116 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/mapping/helpers/tree.rs +1 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/mapping/helpers/tree_policy.inc +781 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/mapping/main/map.rs +7 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/mapping/main/mod.rs +1 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/mapping/mod.rs +4 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/mapping/models.rs +206 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-cli/src/models.rs +11 -8
- fensu_cli-0.3.0/crates/fensu-cli/src/skills/helpers/command/execution.rs +74 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/skills/helpers/command/mod.rs +1 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/skills/helpers/content/discovery.rs +229 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/skills/helpers/content/fingerprint.rs +347 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/skills/helpers/content/mod.rs +4 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/skills/helpers/content/rendering.rs +332 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/skills/helpers/content/sections.rs +360 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/skills/helpers/context/build.rs +135 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/skills/helpers/context/exceptions.rs +111 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/skills/helpers/context/identity.rs +151 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/skills/helpers/context/mod.rs +5 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/skills/helpers/context/options.rs +135 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/skills/helpers/context/selection.rs +292 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/skills/helpers/installation/filesystem.rs +265 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/skills/helpers/installation/freshness.rs +251 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/skills/helpers/installation/install.rs +26 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/skills/helpers/installation/mod.rs +6 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/skills/helpers/installation/plan.rs +120 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/skills/helpers/installation/publication.rs +258 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/skills/helpers/installation/transaction.rs +191 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/skills/helpers/mod.rs +4 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/skills/main/catalogue.rs +11 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/skills/main/core_freshness.rs +7 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/skills/main/execute.rs +13 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/skills/main/mod.rs +4 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/skills/main/skills.rs +24 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/skills/mod.rs +3 -0
- fensu_cli-0.3.0/crates/fensu-cli/src/skills/models.rs +144 -0
- fensu_cli-0.3.0/crates/fensu-cli/tests/command/commands.rs +400 -0
- fensu_cli-0.3.0/crates/fensu-cli/tests/command/helpers.rs +34 -0
- fensu_cli-0.3.0/crates/fensu-cli/tests/command/test_types.rs +12 -0
- fensu_cli-0.3.0/crates/fensu-cli/tests/command.rs +6 -0
- fensu_cli-0.3.0/crates/fensu-cli/tests/mapping/commands.inc +379 -0
- fensu_cli-0.3.0/crates/fensu-cli/tests/mapping/commands.rs +1 -0
- fensu_cli-0.3.0/crates/fensu-cli/tests/mapping/helpers.rs +75 -0
- fensu_cli-0.3.0/crates/fensu-cli/tests/mapping.rs +4 -0
- fensu_cli-0.3.0/crates/fensu-cli/tests/skills/commands.inc +567 -0
- fensu_cli-0.3.0/crates/fensu-cli/tests/skills/commands.rs +1 -0
- fensu_cli-0.3.0/crates/fensu-cli/tests/skills/helpers.rs +80 -0
- fensu_cli-0.3.0/crates/fensu-cli/tests/skills/test_types.rs +26 -0
- fensu_cli-0.3.0/crates/fensu-cli/tests/skills.rs +6 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/Cargo.toml +1 -0
- fensu_cli-0.3.0/crates/fensu-memory/src/source/helpers/bootstrap.rs +177 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/source/helpers/mod.rs +1 -0
- fensu_cli-0.3.0/crates/fensu-memory/src/source/main/bootstrap_memory.rs +10 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/source/main/mod.rs +1 -0
- fensu_cli-0.3.0/crates/fensu-memory/tests/engine/bootstrap.rs +162 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/engine/dependencies.rs +2 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/engine/test_types.rs +8 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/pyproject.toml +1 -1
- fensu_cli-0.2.1/README.md +0 -5
- fensu_cli-0.2.1/crates/fensu-cli/src/command/main/help.rs +0 -3
- fensu_cli-0.2.1/crates/fensu-cli/src/command/mod.rs +0 -1
- fensu_cli-0.2.1/crates/fensu-cli/src/constants.rs +0 -15
- fensu_cli-0.2.1/crates/fensu-cli/src/helpers/config.rs +0 -230
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-cli/assets/catalogue.json +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-cli/assets/python.gitignore +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-cli/build.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-cli/src/command/main/check.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-cli/src/command/main/init.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-cli/src/command/main/rule.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-cli/src/helpers/cache.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-cli/src/helpers/render.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-cli/src/main.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/Cargo.toml +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/constants.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/extension/helpers/conversion/annotations.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/extension/helpers/conversion/contracts.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/extension/helpers/conversion/declarations.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/extension/helpers/conversion/functions.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/extension/helpers/conversion/harness.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/extension/helpers/conversion/hygiene.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/extension/helpers/conversion/mapping.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/extension/helpers/conversion/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/extension/helpers/conversion/references.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/extension/helpers/conversion/rule_authoring.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/extension/helpers/conversion/state.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/extension/helpers/gateway/bindings.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/extension/helpers/gateway/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/extension/helpers/gateway/model_types.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/extension/helpers/gateway/repository_bindings.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/extension/helpers/gateway/rule_authoring_bindings.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/extension/helpers/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/extension/main/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/extension/main/register_module.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/extension/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/extension/models.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/annotations/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/annotations/visitor.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/contracts/category.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/contracts/display.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/contracts/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/contracts/returns.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/contracts/rows.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/control/conditionals.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/control/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/declarations/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/declarations/rows.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/harness/calls.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/harness/dimensions.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/harness/functions.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/harness/imports.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/harness/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/hygiene/checks.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/hygiene/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/metrics/functions.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/metrics/lookups.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/metrics/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/metrics/mutations.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/naming/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/naming/names.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/project/calls.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/project/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/references/events.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/references/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/references/test_shape.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/rule_authoring/literals.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/rule_authoring/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/rule_authoring/mutations.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/rule_authoring/ownership.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/rule_authoring/references.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/shape/breadth.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/shape/children.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/shape/expression_children.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/shape/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/shape/nodes.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/shape/spans.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/shape/statement_children.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/state/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/state/resolution.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/state/scopes.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/wording/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/helpers/wording/text.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/main/enumerate_nodes.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/main/extract_annotations.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/main/extract_class_declarations.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/main/extract_comments.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/main/extract_control_flow.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/main/extract_dataclasses.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/main/extract_evaluate_rule_calls.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/main/extract_function_contracts.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/main/extract_functions.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/main/extract_hygiene.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/main/extract_module_declarations.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/main/extract_outer_state_mutations.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/main/extract_parameter_mutation_occurrences.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/main/extract_parameter_mutations.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/main/extract_project_facts.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/main/extract_references.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/main/extract_rule_calls.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/main/extract_rule_references.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/main/extract_test_functions.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/main/extract_test_module.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/main/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/mapping/constants.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/mapping/helpers/classes.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/mapping/helpers/expressions.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/mapping/helpers/extraction.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/mapping/helpers/functions.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/mapping/helpers/imports.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/mapping/helpers/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/mapping/main/extract_mapping_declarations.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/mapping/main/extract_mapping_facts.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/mapping/main/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/mapping/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/mapping/models.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/models.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/facts/types.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/lib.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/parsing/helpers/failures.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/parsing/helpers/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/parsing/main/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/parsing/main/parse_expression_strict.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/parsing/main/parse_strict.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/parsing/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/parsing/models.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/positions/helpers/line_index.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/positions/helpers/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/positions/main/index_lines.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/positions/main/locate_offset.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/positions/main/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/positions/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/positions/models.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/snapshot/constants.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/snapshot/helpers/matching.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/snapshot/helpers/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/snapshot/helpers/observation_index.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/snapshot/helpers/repository_observation_index.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/snapshot/helpers/repository_paths.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/snapshot/main/build_repository_observation_index.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/snapshot/main/hash_files.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/snapshot/main/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/snapshot/main/walk_python_files.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/snapshot/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/src/snapshot/models.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/tests/facts/enumerate.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/tests/facts/mapping.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/tests/facts/rule_authoring.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/tests/facts/test_types.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/tests/facts.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/tests/parsing/strict.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/tests/parsing/test_types.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/tests/parsing.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/tests/positions/locate.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/tests/positions/test_types.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/tests/positions.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/tests/snapshot/hashing.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/tests/snapshot/helpers.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/tests/snapshot/observations.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/tests/snapshot/test_types.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/tests/snapshot/walk.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-facts/tests/snapshot.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/corpus/helpers/loading.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/corpus/helpers/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/corpus/main/load_discovered_memory_corpus.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/corpus/main/load_memory_corpus.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/corpus/main/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/corpus/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/corpus/models.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/corpus/types.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/constants.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/errors.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/helpers/archival/archive.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/helpers/archival/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/helpers/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/helpers/publication/database.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/helpers/publication/documents.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/helpers/publication/lists.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/helpers/publication/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/helpers/publication/references.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/helpers/publication/sections.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/helpers/publication/skills.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/helpers/publication/streaming.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/helpers/publication/values.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/helpers/querying/graph_loading.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/helpers/querying/graphs.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/helpers/querying/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/helpers/querying/overviews.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/helpers/querying/queries.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/helpers/querying/query_values.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/helpers/reporting/diagnostics.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/helpers/reporting/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/helpers/reporting/schema_core.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/helpers/reporting/schema_markdown.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/helpers/reporting/schema_metadata.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/helpers/reporting/schema_skill_view.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/helpers/reporting/schema_views.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/helpers/reporting/summaries.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/helpers/reporting/synchronization.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/main/archive_memory.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/main/check_memory.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/main/memory_overview.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/main/memory_relation_schema.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/main/memory_schema.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/main/memory_schema_sql.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/main/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/main/probe_dependencies.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/main/query_memory_graph.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/main/query_memory_index.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/main/rebuild_memory_index.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/main/summarize_memory.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/main/sync_memory_index.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/engine/models.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/graph/helpers/cycles.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/graph/helpers/dependencies.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/graph/helpers/document_targets.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/graph/helpers/heading_targets.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/graph/helpers/link_resolution.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/graph/helpers/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/graph/main/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/graph/main/resolve_memory_graph.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/graph/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/graph/models.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/graph/types.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/lib.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/markdown/constants.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/markdown/helpers/assembly.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/markdown/helpers/blocks.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/markdown/helpers/headings.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/markdown/helpers/line_index.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/markdown/helpers/links.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/markdown/helpers/lists.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/markdown/helpers/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/markdown/helpers/obsidian.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/markdown/helpers/text.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/markdown/main/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/markdown/main/parse_markdown.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/markdown/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/markdown/models.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/markdown/types.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/source/constants.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/source/helpers/collisions.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/source/helpers/discovery.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/source/helpers/documents.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/source/helpers/filesystem.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/source/helpers/git_tracking.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/source/helpers/skills.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/source/helpers/tree.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/source/helpers/validation.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/source/main/discover_memory.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/source/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/source/models.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/src/source/types.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/corpus/helpers.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/corpus/loading.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/corpus/test_types.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/corpus.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/engine/archive.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/engine/check.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/engine/graph_query.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/engine/helpers.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/engine/list_batch/list_batches.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/engine/list_batch/test_types.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/engine/overview.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/engine/performance.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/engine/query.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/engine/schema.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/engine/streaming/helpers.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/engine/streaming.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/engine/summary.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/engine/sync.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/engine.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/graph/dependencies.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/graph/helpers.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/graph/resolution.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/graph/test_types.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/graph.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/markdown/code_blocks.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/markdown/links.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/markdown/lists.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/markdown/structure.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/markdown/test_types.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/markdown.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/source/collisions.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/source/discovery.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/source/git_worktrees.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/source/helpers.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/source/symlinks.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/source/test_types.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-memory/tests/source.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/Cargo.toml +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/cache/constants.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/cache/helpers/bindings.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/cache/helpers/database.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/cache/helpers/generation.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/cache/helpers/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/cache/helpers/publication.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/cache/helpers/publication_merge.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/cache/helpers/records.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/cache/helpers/replay.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/cache/helpers/schema.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/cache/helpers/schema_values.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/cache/helpers/storage.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/cache/main/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/cache/main/register_cache.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/cache/main/replay_generation.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/cache/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/cache/models.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/cache/types.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/extension/constants.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/extension/helpers/core_rule_bindings.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/extension/helpers/execution_planning.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/extension/helpers/memory_bindings.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/extension/helpers/memory_conversion.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/extension/helpers/memory_registration.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/extension/helpers/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/extension/main/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/extension/main/register_module.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/extension/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/lib.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/rules/constants.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/rules/helpers/annotations/annotations.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/rules/helpers/hygiene/hygiene.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/rules/helpers/layers/layers.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/rules/helpers/layers/local.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/rules/helpers/layers/project.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/rules/helpers/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/rules/helpers/naming/naming.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/rules/helpers/naming_globs/naming_globs.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/rules/helpers/project_queries/project_queries.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/rules/helpers/roles/declarations.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/rules/helpers/roles/paths.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/rules/helpers/roles/project_layout.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/rules/helpers/roles/project_layout_paths.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/rules/helpers/roles/project_layout_queries.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/rules/helpers/roles/roles.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/rules/helpers/roles/surfaces.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/rules/helpers/shape/shape.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/rules/helpers/tests/layout.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/rules/helpers/tests/names.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/rules/helpers/tests/tests.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/rules/main/evaluate_core_rules.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/rules/main/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/rules/main/plan_core_rule_queries.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/rules/mod.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/src/rules/models.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/tests/extension/memory_conversion.rs +0 -0
- {fensu_cli-0.2.1 → fensu_cli-0.3.0}/crates/fensu-native/tests/extension/test_types.rs +0 -0
|
@@ -344,8 +344,10 @@ checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6"
|
|
|
344
344
|
|
|
345
345
|
[[package]]
|
|
346
346
|
name = "fensu-cli"
|
|
347
|
-
version = "0.
|
|
347
|
+
version = "0.3.0"
|
|
348
348
|
dependencies = [
|
|
349
|
+
"dunce",
|
|
350
|
+
"encoding_rs",
|
|
349
351
|
"fensu-facts",
|
|
350
352
|
"fensu-memory",
|
|
351
353
|
"fensu-native",
|
|
@@ -356,7 +358,9 @@ dependencies = [
|
|
|
356
358
|
"serde",
|
|
357
359
|
"serde_json",
|
|
358
360
|
"sha2",
|
|
361
|
+
"tempfile",
|
|
359
362
|
"toml",
|
|
363
|
+
"unicode-normalization",
|
|
360
364
|
"walkdir",
|
|
361
365
|
]
|
|
362
366
|
|
|
@@ -382,6 +386,7 @@ version = "0.1.0"
|
|
|
382
386
|
dependencies = [
|
|
383
387
|
"gix",
|
|
384
388
|
"hex",
|
|
389
|
+
"libc",
|
|
385
390
|
"pulldown-cmark",
|
|
386
391
|
"rayon",
|
|
387
392
|
"rusqlite",
|
|
@@ -9,10 +9,12 @@ publish = false
|
|
|
9
9
|
|
|
10
10
|
[workspace.dependencies]
|
|
11
11
|
dunce = "1.0"
|
|
12
|
+
encoding_rs = "0.8"
|
|
12
13
|
flate2 = { version = "1", default-features = false, features = ["zlib"] }
|
|
13
14
|
gix = { version = "0.85.0", default-features = false, features = ["excludes", "sha1"] }
|
|
14
15
|
globset = "0.4"
|
|
15
16
|
hex = "0.4"
|
|
17
|
+
libc = "0.2"
|
|
16
18
|
proc-macro2 = { version = "1", features = ["span-locations"] }
|
|
17
19
|
pyo3 = { version = "0.29", features = ["abi3-py312"] }
|
|
18
20
|
pulldown-cmark = { version = "0.13.4", default-features = false }
|
|
@@ -32,6 +34,7 @@ syn = { version = "2", features = ["full", "visit", "extra-traits"] }
|
|
|
32
34
|
tempfile = "3"
|
|
33
35
|
toml = "0.9"
|
|
34
36
|
unicode-ident = "1"
|
|
37
|
+
unicode-normalization = "0.1"
|
|
35
38
|
walkdir = "2"
|
|
36
39
|
|
|
37
40
|
[workspace.lints.rust]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fensu-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Classifier: Development Status :: 3 - Alpha
|
|
5
5
|
Classifier: Intended Audience :: Developers
|
|
6
6
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
@@ -16,7 +16,7 @@ Project-URL: Repository, https://github.com/chio-labs/fensu
|
|
|
16
16
|
|
|
17
17
|
# fensu-cli
|
|
18
18
|
|
|
19
|
-
This package supplies the native `fensu` executable. Install `fensu` for
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
This package supplies the native `fensu` executable. Install `fensu` for the
|
|
20
|
+
Python authoring API, native extension, callback host, and this binary as one
|
|
21
|
+
locked dependency set.
|
|
22
22
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "fensu-cli"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.3.0" # x-release-please-version
|
|
4
4
|
edition.workspace = true
|
|
5
5
|
license.workspace = true
|
|
6
6
|
publish = false
|
|
@@ -14,6 +14,8 @@ name = "fensu"
|
|
|
14
14
|
path = "src/main.rs"
|
|
15
15
|
|
|
16
16
|
[dependencies]
|
|
17
|
+
dunce.workspace = true
|
|
18
|
+
encoding_rs.workspace = true
|
|
17
19
|
globset.workspace = true
|
|
18
20
|
rayon.workspace = true
|
|
19
21
|
ruff_python_ast.workspace = true
|
|
@@ -23,10 +25,14 @@ serde_json.workspace = true
|
|
|
23
25
|
sha2.workspace = true
|
|
24
26
|
fensu-facts = { workspace = true, default-features = false }
|
|
25
27
|
# Keep the complete local workspace dependency graph in the CLI sdist.
|
|
26
|
-
fensu-memory
|
|
28
|
+
fensu-memory = { workspace = true, features = ["sqlite-engine"] }
|
|
27
29
|
fensu-native = { workspace = true, default-features = false }
|
|
28
30
|
toml.workspace = true
|
|
31
|
+
unicode-normalization.workspace = true
|
|
29
32
|
walkdir.workspace = true
|
|
30
33
|
|
|
34
|
+
[dev-dependencies]
|
|
35
|
+
tempfile.workspace = true
|
|
36
|
+
|
|
31
37
|
[build-dependencies]
|
|
32
38
|
serde_json.workspace = true
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"authoring_lookup":["## Approved Custom Rule Authoring Lookup","","When authoring an approved custom rule, use the generated RuleContext summary first. If exact signatures or returned public models are unclear, inspect existing repository custom rules, then the public Fensu exports and type definitions from the project's active Python environment. This targets the installed Fensu version rather than remembered or generic API knowledge.","","It is acceptable to locate the active installation through `fensu.__file__` or the project's `.venv` and read definitions behind public exports such as `RuleContext`, semantic fact protocols, project-query protocols, and public result models. Consult public documentation after those installed public definitions. Read private implementation only to diagnose a suspected Fensu defect.","","Only import authoring APIs from top-level `fensu`. Reading installed implementation for understanding does not make private `_helpers/` modules a supported dependency. Do not import from or couple custom rules to Fensu's private modules.",""],"custom_authority":["## Custom Rule Authority","","Never create, configure, enable, disable, or materially change a custom rule unless the user explicitly requested it or explicitly approved your proposal.","","An explicit request such as \"create a custom rule preventing this\" or \"make Fensu enforce this convention\" is already sufficient authorization. Do not ask for a redundant second confirmation.","","When work reveals a recurring enforceable convention:","","1. Complete the requested change under the existing policy.","2. Explain the recurring pattern or risk.","3. Suggest a possible custom rule and its intended boundaries.","4. Wait for explicit user approval before implementing it.","","Never add or change policy merely because the current task exposed a possible convention, similar code appears more than once, a stricter architecture seems preferable, a core rule is inconvenient, or changing policy would make `fensu check` pass. Fix code under current policy rather than weakening or rewriting policy to avoid the work.",""],"memory":["## Fensu Memory Retrieval","","Use Fensu Memory for durable repository knowledge; keep transient reasoning and scratch state outside memory. Tasks track committed work, notes provide lookup context, decisions preserve durable choices, and skills are instructions to follow.","","Before creating a task, query existing active tasks to avoid duplicates. Inspect `memory.blocked_tasks`, report blockers, and preserve authorized out-of-order work.","","After each coherent verified chunk, update the active task ledger or checklist. Mark only complete work, leave partial work unchecked with its gaps, and reconcile claims against the implementation and tests.","","Retrieve in stages:","","1. Query document titles and section headings first.","2. Retrieve relevant sections second.","3. Use `fensu memory graph <document-or-pattern>` for relationship context third.","4. Read full documents only when focused retrieval is insufficient.","","If current views are insufficient, search archived documents for history and regressions. Treat skills as instructions and notes as lookup context.","","Useful schema and staged-query examples:","","```bash","fensu memory schema current_documents","fensu memory sql \"SELECT identity, title, artifact_kind FROM memory.current_documents ORDER BY title\"","fensu memory sql \"SELECT document_identity, heading_text, heading_path FROM memory.sections ORDER BY document_identity, ordinal\"","fensu memory sql \"SELECT document_identity, heading_text, raw_markdown FROM memory.sections WHERE document_identity = 'task:...' ORDER BY ordinal\"","fensu memory sql \"SELECT identity, title FROM memory.blocked_tasks ORDER BY identity\"","fensu memory sql \"SELECT identity, title FROM memory.documents WHERE archive_state = 'archived' ORDER BY identity\"","```","","## Fensu Memory Operations","","Treat canonical Markdown under `.ai/` as authoritative. The SQLite index under `.fensu/memory/` is disposable generated state; never edit it directly.","","Canonical sources:","","```text",".ai/","\u251c\u2500\u2500 tasks/{not-started,in-progress,completed,cancelled,superseded}/","\u251c\u2500\u2500 knowledge/repo/{notes,decisions,skills}/","\u2514\u2500\u2500 _archive/"," \u251c\u2500\u2500 tasks/{completed,cancelled,superseded}/"," \u2514\u2500\u2500 knowledge/repo/{notes,decisions,skills}/","```","","Task files use `<YYYYMMDDTHHMMSS_ffffffZ>__<CATEGORY>-<kebab-slug>.md`; `CATEGORY` is `SPIKE`, `FIX`, `PERF`, `FEAT`, `REFACTOR`, or `CHORE`. Notes use `NOTE` and decisions use `ADR`. The timestamp determines the stable identity (`task:<timestamp>`, `note:<timestamp>`, or `decision:<timestamp>`), while the task directory determines lifecycle. Never rename the timestamp to change state.","","Locate a document before editing it:","","```bash","fensu memory sql \"SELECT identity, filesystem_path FROM memory.current_documents WHERE identity = 'task:...'\"","```","","Edit the returned canonical Markdown path, then run `fensu memory sync`. To change a task lifecycle, move the unchanged file between live lifecycle directories with a plain filesystem move; sources may be untracked, so do not assume `git mv` applies.","","Create a task only after querying active tasks for duplicates. Add a correctly named document under `.ai/tasks/not-started/`, mirror the structure of nearby tasks, then run `fensu memory sync`.","","Run `fensu memory check` for canonical-source diagnostics. Use `fensu memory archive` for age-based archival, or pass explicit paths and `--yes` for terminal tasks; never move documents into `.ai/_archive/` manually. Automatic task archival uses the configured `987654321`-day retention.","","## Phased Implementation","","Execute task documents as vertical slices. Each slice must leave the affected flow working, verified, and shippable; do not implement horizontal layers such as all models before all wiring.","","For each slice: implement, verify with the narrowest faithful tests plus relevant Fensu checks or parity evidence, update only the task checkboxes proven by that evidence, then begin the next slice. Leave partial work unchecked and record its gap.","","Write task phases as observable end-to-end outcomes, each with checkboxes and an explicit verification gate. Example:","","```markdown","## Phase 1: Native Memory Check","","- [ ] Parse `memory check` in the Rust CLI, call the native engine, render exact faults,"," and preserve exit codes without launching Python.","- [ ] Add command-parity and process-accounting coverage.","","Verification: focused Rust and CLI tests pass; output matches the Python oracle; the","process trace contains no Python executable.","```","","This is one vertical slice because it delivers one usable behavior through every affected layer. Separate phases such as `Add models`, `Add helpers`, and `Wire CLI` are horizontal work queues and are not acceptable slices.","","For performance work, use paired A/B measurements, keep or revert from evidence, and record retained and rejected results in the task ledger.",""],"navigation":["## Navigation And Work Handoffs","","For any non-trivial change that crosses module or package boundaries, run `fensu map <symbol> --depth 4` before editing. Rerun the same map after implementation to explain the changed flow. Skip only isolated single-file edits.","","Treat the map as a deterministic call skeleton whose primary benefit is helping the user understand the system, not proving that the agent explored it. Do not paste a raw map as the handoff. Read the relevant source to explain purpose and branches, use the diff to identify what changed and why, and use checks and tests to state what was verified. Never guess through unresolved calls. If the map cannot resolve the flow, state that and continue with direct source inspection.","","After a substantial chunk of work, rerun `fensu check` and the same map. Include a user-facing walkthrough only when it materially clarifies a multi-module change. Default to the smallest affected branch, normally three to eight lines:","","```text","build_result(...) domain/main/build.py:24","\u2514\u2500\u2500 assemble_result(...) domain/_helpers/assemble.py:41"," CHANGED: state the behavioral difference and why it was made.","VERIFIED: name the check that proves the changed boundary.","```","","Replace the template with facts from the repository. Preserve enough parent context to orient the user, but omit unchanged branches that do not aid understanding. Use a full before/after walkthrough only when ownership or phase boundaries changed substantially. `DONE`, `PENDING`, and `WE ARE HERE` are agent-authored work-state annotations, not Fensu output.","","Every displayed function must include its repository-relative path and line when available. Mark changed nodes with `CHANGED` and explain the behavioral difference and reason, not merely that a file changed. Mark supporting evidence with `VERIFIED`. When static mapping omits protocol or dynamic dispatch, stitch in the continuation only after confirming it from source and label it `SOURCE-RESOLVED DYNAMIC BOUNDARY` so the user can distinguish map output from inspected runtime wiring.","","Do not force a graph into a handoff when one sentence with a clickable `path:line` communicates the change more clearly.",""],"repository":["## Repository Structure","","Only structures established by this repository's active core rules are shown. Omitted structures are not implied.","","### Runtime","","Leaf domain:","","```text","__ROOT__/","\u2514\u2500\u2500 <domain>/"," \u251c\u2500\u2500 main/"," \u251c\u2500\u2500 _helpers/"," \u251c\u2500\u2500 classes/"," \u251c\u2500\u2500 models.py"," \u251c\u2500\u2500 types.py"," \u251c\u2500\u2500 constants.py"," \u2514\u2500\u2500 exceptions.py","```","","Branch domain:","","```text","__ROOT__/","\u2514\u2500\u2500 <domain>/"," \u2514\u2500\u2500 <subdomain>/"," \u251c\u2500\u2500 main/"," \u251c\u2500\u2500 _helpers/"," \u251c\u2500\u2500 classes/"," \u251c\u2500\u2500 models.py"," \u251c\u2500\u2500 types.py"," \u251c\u2500\u2500 constants.py"," \u2514\u2500\u2500 exceptions.py","```","","### Domain Shape","","Domains may be leaves with role content directly beneath `<domain>/`, or branches containing named subdomains. Do not mix the two shapes.","","For a singleton capability, prefer a leaf instead of creating a placeholder `core` subdomain.","","Promote a leaf to a branch only when multiple real capabilities exist.","","Every leaf domain or subdomain must contain a direct `main/` boundary with at least one non-`__init__.py` Python entry module. Branch-domain parents do not need their own `main/`; their leaf subdomains do.","","Do not add placeholder `main/` packages. If a package owns only passive models, types, constants, exceptions, or classes, move them into the closest domain or subdomain whose `main/` behavior owns and uses them.","","Generic package names are banned, including `base`, `common`, `lib`, `misc`, `shared`, `util`, and `utils`. Name the business domain or technical capability owner instead.","","### Role Containers","","#### `_helpers/`: Flat Or Grouped","","Each `_helpers/` container has an effective module limit; its configured role base is 10.","","```text","_helpers/","\u251c\u2500\u2500 first_helper.py","\u2514\u2500\u2500 second_helper.py","```","","or group every module:","","```text","_helpers/","\u251c\u2500\u2500 reading/","\u2502 \u2514\u2500\u2500 read_helper.py","\u2514\u2500\u2500 writing/"," \u2514\u2500\u2500 write_helper.py","```","","#### `main/`: Flat Or Grouped","","Each `main/` container has an effective module limit; its configured role base is 20.","","```text","main/","\u251c\u2500\u2500 first_entry.py","\u2514\u2500\u2500 second_entry.py","```","","or group every module:","","```text","main/","\u251c\u2500\u2500 reading/","\u2502 \u2514\u2500\u2500 read_entry.py","\u2514\u2500\u2500 writing/"," \u2514\u2500\u2500 write_entry.py","```","","Every container holds direct Python modules or Python-containing buckets, never both. Empty and asset-only directories do not count as buckets.","","Configured base `max_role_depth` is 1. Role tables and matching path overrides can provide the effective per-path value.","","Runtime role names are banned as buckets: `main`, `_helpers`, `classes`, `models`, `types`, `constants`, and `exceptions`.","","Generic bucket names remain FFR204 concerns and do not receive a second container-layout fault.","","Fixed role filenames such as `models.py`, `types.py`, `constants.py`, and `exceptions.py` are sibling roles and must never be nested beneath `_helpers/`.","","Every non-`__init__.py` module whose first structural role is `main` is an entry module, including grouped main modules. Entry shape and container depth are orthogonal, so an over-depth main path may independently receive both layout and entry-shape diagnostics. A `main` bucket below another role is not an entry boundary.","","### Role Examples","","#### `main/read_invoice.py`","","Expose exactly one public entry function and keep phase work in _helpers/. Use up to two private functions only when entry-specific glue is genuinely needed:","","```python","from __ROOT__.invoices._helpers.loading import load_invoice","from __ROOT__.invoices._helpers.normalization import normalize_invoice","from __ROOT__.invoices.models import Invoice","","def read_invoice(invoice_id: str) -> Invoice:"," loaded: Invoice = load_invoice(invoice_id)"," return normalize_invoice(loaded)","```","","#### `models.py`","","```python","from dataclasses import dataclass","","@dataclass(frozen=True, slots=True)","class Invoice:"," identifier: str"," total_cents: int","```","","When Pydantic is already in use, its structured models belong in the same role:","","```python","from pydantic import BaseModel","","class InvoiceQuery(BaseModel):"," customer_id: str"," include_paid: bool = False","```","","#### `_helpers/normalization.py`","","Private constants and support dataclasses precede helper functions:","","```python","from dataclasses import dataclass","","_DEFAULT_CURRENCY: str = \"USD\"","","@dataclass(frozen=True, slots=True)","class _NormalizedAmount:"," cents: int"," currency: str","","def normalize_amount(cents: int) -> _NormalizedAmount:"," return _NormalizedAmount(cents=max(cents, 0), currency=_DEFAULT_CURRENCY)","```","","#### `classes/invoice_repository.py`","","Each module under `classes/` defines exactly one top-level class:","","```python","from __ROOT__.invoices.models import Invoice","","class InvoiceRepository:"," def __init__(self, invoices: dict[str, Invoice]) -> None:"," self._invoices = invoices",""," def read(self, invoice_id: str) -> Invoice:"," return self._invoices[invoice_id]","```","","#### `types.py`","","```python","from enum import StrEnum","from typing import NewType, TypeAlias","","InvoiceId = NewType(\"InvoiceId\", str)","InvoiceLine: TypeAlias = tuple[str, int]","","class InvoiceState(StrEnum):"," DRAFT = \"draft\""," PAID = \"paid\"","```","","#### `constants.py`","","```python","DEFAULT_PAGE_SIZE: int = 100","MAX_RETRY_ATTEMPTS: int = 3","```","","#### `exceptions.py`","","```python","class InvoiceNotFoundError(LookupError):"," \"\"\"Raised when an invoice identifier is unknown.\"\"\"","```","","### Tests","","```text","__TEST__/","\u2514\u2500\u2500 <scope>/"," \u2514\u2500\u2500 __ROOT__/<domain>[/<subdomain>]/"," \u251c\u2500\u2500 _test_types.py"," \u2514\u2500\u2500 test_feature.py","```","","`_test_types.py`:","","```python","from dataclasses import dataclass","","@dataclass(frozen=True)","class ReadInvoiceTestCase:"," description: str"," invoice_id: str"," expected_identifier: str","```","","`test_feature.py`:","","```python","import pytest","","from __ROOT__.invoices.main.read_invoice import read_invoice","from __ROOT__.invoices.models import Invoice","from __TEST__.unit.__ROOT__.invoices._test_types import ReadInvoiceTestCase","","@pytest.mark.parametrize("," \"test_case\","," ["," ReadInvoiceTestCase("," description=\"returns the requested invoice\","," invoice_id=\"invoice-1\","," expected_identifier=\"invoice-1\","," )"," ],"," ids=lambda case: case.description,",")","def test_given_invoice_id_when_reading_invoice_then_returns_expected_invoice("," test_case: ReadInvoiceTestCase,",") -> None:"," result: Invoice = read_invoice(test_case.invoice_id)",""," assert result.identifier == test_case.expected_identifier","```",""],"repository_tooling":["## Repository Structure","","Only structures established by this repository's active core rules are shown. Omitted structures are not implied.","","### Runtime","","Leaf domain:","","```text","__ROOT__/","\u2514\u2500\u2500 <domain>/"," \u251c\u2500\u2500 main/"," \u251c\u2500\u2500 _helpers/"," \u251c\u2500\u2500 classes/"," \u251c\u2500\u2500 models.py"," \u251c\u2500\u2500 types.py"," \u251c\u2500\u2500 constants.py"," \u2514\u2500\u2500 exceptions.py","```","","Branch domain:","","```text","__ROOT__/","\u2514\u2500\u2500 <domain>/"," \u2514\u2500\u2500 <subdomain>/"," \u251c\u2500\u2500 main/"," \u251c\u2500\u2500 _helpers/"," \u251c\u2500\u2500 classes/"," \u251c\u2500\u2500 models.py"," \u251c\u2500\u2500 types.py"," \u251c\u2500\u2500 constants.py"," \u2514\u2500\u2500 exceptions.py","```","","### Domain Shape","","Domains may be leaves with role content directly beneath `<domain>/`, or branches containing named subdomains. Do not mix the two shapes.","","For a singleton capability, prefer a leaf instead of creating a placeholder `core` subdomain.","","Promote a leaf to a branch only when multiple real capabilities exist.","","Every leaf domain or subdomain must contain a direct `main/` boundary with at least one non-`__init__.py` Python entry module. Branch-domain parents do not need their own `main/`; their leaf subdomains do.","","Do not add placeholder `main/` packages. If a package owns only passive models, types, constants, exceptions, or classes, move them into the closest domain or subdomain whose `main/` behavior owns and uses them.","","Generic package names are banned, including `base`, `common`, `lib`, `misc`, `shared`, `util`, and `utils`. Name the business domain or technical capability owner instead.","","### Role Containers","","#### `_helpers/`: Flat Or Grouped","","Each `_helpers/` container has an effective module limit; its configured role base is 10.","","```text","_helpers/","\u251c\u2500\u2500 first_helper.py","\u2514\u2500\u2500 second_helper.py","```","","or group every module:","","```text","_helpers/","\u251c\u2500\u2500 reading/","\u2502 \u2514\u2500\u2500 read_helper.py","\u2514\u2500\u2500 writing/"," \u2514\u2500\u2500 write_helper.py","```","","#### `main/`: Flat Or Grouped","","Each `main/` container has an effective module limit; its configured role base is 20.","","```text","main/","\u251c\u2500\u2500 first_entry.py","\u2514\u2500\u2500 second_entry.py","```","","or group every module:","","```text","main/","\u251c\u2500\u2500 reading/","\u2502 \u2514\u2500\u2500 read_entry.py","\u2514\u2500\u2500 writing/"," \u2514\u2500\u2500 write_entry.py","```","","Every container holds direct Python modules or Python-containing buckets, never both. Empty and asset-only directories do not count as buckets.","","Configured base `max_role_depth` is 1. Role tables and matching path overrides can provide the effective per-path value.","","Runtime role names are banned as buckets: `main`, `_helpers`, `classes`, `models`, `types`, `constants`, and `exceptions`.","","Generic bucket names remain FFR204 concerns and do not receive a second container-layout fault.","","Fixed role filenames such as `models.py`, `types.py`, `constants.py`, and `exceptions.py` are sibling roles and must never be nested beneath `_helpers/`.","","Every non-`__init__.py` module whose first structural role is `main` is an entry module, including grouped main modules. Entry shape and container depth are orthogonal, so an over-depth main path may independently receive both layout and entry-shape diagnostics. A `main` bucket below another role is not an entry boundary.","","### Role Examples","","#### `main/read_invoice.py`","","Expose exactly one public entry function and keep phase work in _helpers/. Use up to two private functions only when entry-specific glue is genuinely needed:","","```python","from __ROOT__.invoices._helpers.loading import load_invoice","from __ROOT__.invoices._helpers.normalization import normalize_invoice","from __ROOT__.invoices.models import Invoice","","def read_invoice(invoice_id: str) -> Invoice:"," loaded: Invoice = load_invoice(invoice_id)"," return normalize_invoice(loaded)","```","","#### `models.py`","","```python","from dataclasses import dataclass","","@dataclass(frozen=True, slots=True)","class Invoice:"," identifier: str"," total_cents: int","```","","When Pydantic is already in use, its structured models belong in the same role:","","```python","from pydantic import BaseModel","","class InvoiceQuery(BaseModel):"," customer_id: str"," include_paid: bool = False","```","","#### `_helpers/normalization.py`","","Private constants and support dataclasses precede helper functions:","","```python","from dataclasses import dataclass","","_DEFAULT_CURRENCY: str = \"USD\"","","@dataclass(frozen=True, slots=True)","class _NormalizedAmount:"," cents: int"," currency: str","","def normalize_amount(cents: int) -> _NormalizedAmount:"," return _NormalizedAmount(cents=max(cents, 0), currency=_DEFAULT_CURRENCY)","```","","#### `classes/invoice_repository.py`","","Each module under `classes/` defines exactly one top-level class:","","```python","from __ROOT__.invoices.models import Invoice","","class InvoiceRepository:"," def __init__(self, invoices: dict[str, Invoice]) -> None:"," self._invoices = invoices",""," def read(self, invoice_id: str) -> Invoice:"," return self._invoices[invoice_id]","```","","#### `types.py`","","```python","from enum import StrEnum","from typing import NewType, TypeAlias","","InvoiceId = NewType(\"InvoiceId\", str)","InvoiceLine: TypeAlias = tuple[str, int]","","class InvoiceState(StrEnum):"," DRAFT = \"draft\""," PAID = \"paid\"","```","","#### `constants.py`","","```python","DEFAULT_PAGE_SIZE: int = 100","MAX_RETRY_ATTEMPTS: int = 3","```","","#### `exceptions.py`","","```python","class InvoiceNotFoundError(LookupError):"," \"\"\"Raised when an invoice identifier is unknown.\"\"\"","```","","### Tests","","```text","__TEST__/","\u2514\u2500\u2500 <scope>/"," \u2514\u2500\u2500 __ROOT__/<domain>[/<subdomain>]/"," \u251c\u2500\u2500 _test_types.py"," \u2514\u2500\u2500 test_feature.py","```","","Tooling-backed tests mirror under `__TEST__/<scope>/__TOOL__/<area>/`.","","`_test_types.py`:","","```python","from dataclasses import dataclass","","@dataclass(frozen=True)","class ReadInvoiceTestCase:"," description: str"," invoice_id: str"," expected_identifier: str","```","","`test_feature.py`:","","```python","import pytest","","from __ROOT__.invoices.main.read_invoice import read_invoice","from __ROOT__.invoices.models import Invoice","from __TEST__.unit.__ROOT__.invoices._test_types import ReadInvoiceTestCase","","@pytest.mark.parametrize("," \"test_case\","," ["," ReadInvoiceTestCase("," description=\"returns the requested invoice\","," invoice_id=\"invoice-1\","," expected_identifier=\"invoice-1\","," )"," ],"," ids=lambda case: case.description,",")","def test_given_invoice_id_when_reading_invoice_then_returns_expected_invoice("," test_case: ReadInvoiceTestCase,",") -> None:"," result: Invoice = read_invoice(test_case.invoice_id)",""," assert result.identifier == test_case.expected_identifier","```","","### Tooling","","```text","__TOOL__/","\u251c\u2500\u2500 run_tool.py","\u2514\u2500\u2500 <tool>/"," \u251c\u2500\u2500 main/"," \u251c\u2500\u2500 _helpers/"," \u251c\u2500\u2500 classes/"," \u2514\u2500\u2500 rules/","```",""],"rule_context":["## RuleContext Public API","","Approved custom rules receive `ctx: RuleContext`. Import authoring APIs only from the top-level `fensu` package. The five public analysis zones are:","","- `ctx.facts`: `annotations()`, `assignment_references()`, `class_declarations()`, `comments()`, `comparisons()`, `complex_comprehensions()`, `dataclasses()`, `function_conditionals()`, `functions()`, `function_contracts()`, `hygiene()`, `meaningful_returns(name_patterns=())`, `local_call_edges()`, `module_declarations()`, `named_calls()`, `outer_state_mutations()`, `parameter_mutations()`, `parameter_mutation_occurrences()`, `project_calls()`, `project_functions()`, `references()`, `test_functions()`, `top_level_definition_conditionals()`, and `test_module()`.","- `ctx.text`: `source`, `line(line_number)`, and `slice(source_range)`.","- `ctx.syntax`: `handles(kind=None)`, `kind(handle)`, and `range(handle)`.","- `ctx.relations`: `parent(handle)`, `children(handle)`, and `ancestors(handle)`.","- `ctx.project`: dependency-recording cross-file and filesystem queries. Use `analysis(requester=ctx.path, path=path)`, `dataclasses(requester=ctx.path, path=path)`, `directory_entries(requester=ctx.path, path=path)`, `entrypoint_modules(requester=ctx.path)`, `module_function(requester=ctx.path, module_name=name, function_name=name)`, `python_anchor(requester=ctx.path, path=path)`, `exists(requester=ctx.path, path=path)`, `is_dir(requester=ctx.path, path=path)`, `is_file(requester=ctx.path, path=path)`, and `glob(requester=ctx.path, path=path, pattern=pattern, recursive=False)`. Inspect recorded observations with `dependencies()` or `dependencies_for(requester=ctx.path)`.","","Position and ownership helpers: `ctx.path`, `ctx.repo_root`, `ctx.source`, `relative_parts()`, `repo_relative_parts()`, `scope_root()`, `scope_roots(scope)`, `module_parts()`, `scope()`, `role_of()`, `in_role(role)`, `is_entry_module()`, `is_main_module()`, `domain()`, and `subdomain()`. `role_of()` describes the current file here; use project facts rather than assuming arbitrary paths share its position.","","AST helpers: `nodes(node_type)`, `call_name(node)`, `base_name(node)`, `top_level_functions(module)`, `non_docstring_body(module)`, `distinct_callees(fn)`, `assigned_locals(fn)`, `complex_comprehensions()`, `parameter_names(fn)`, and `inside_loop(node)`.","","Policy helpers: `threshold(name=..., path=None)` and `contracts()`. Fault constructors: `fault(node=..., message=None, remediation=None)`, `fault_at(location=..., message=None, remediation=None)`, `fault_for(path=..., line=..., column=..., message=None, remediation=None)`, and `path_fault(path=None, message=None, remediation=None)`.",""],"work_practices":["## Working With Existing Drift","","The user request defines the scope of remediation. A large fault count is an architectural baseline, not authorization to fix unrelated code.","","- If the user requests one change, do not expand into unrelated fault remediation.","- If the user explicitly requests a broader refactor, particular fault families, or zero faults, treat that broader target as authorized scope.","- Satisfy faults by improving code under the current policy. Do not weaken selection, thresholds, exceptions, or custom rules unless the user explicitly requests a policy change.","- Before moving or splitting behavior, map the affected call flow and run the existing tests.","- When coverage around changed behavior is weak or unknown, add focused characterization tests before refactoring.","- Preserve behavior first and improve structure in verifiable slices.","- Distinguish pre-existing faults from regressions introduced by the current work.","","For an explicitly authorized broad refactor, capture the baseline, map affected flows, establish characterization coverage, work in coherent slices, verify each slice, and run full final verification. A request to make `fensu check` pass means fix the code under the current policy, not edit configuration until findings disappear.","","## Testing Refactors Safely","","Before materially restructuring behavior, inspect the existing tests. When the affected behavior is weakly covered or its coverage is uncertain, add focused characterization tests before moving code.","","Use the cheapest test that faithfully exercises the risk:","","- Unit tests for isolated decisions, transformations, and error handling.","- Integration tests for storage, messaging, process, and adapter boundaries.","- End-to-end tests for user-visible commands and workflows.","- Real local dependencies when they are deterministic and reasonably inexpensive.","","Prefer faithful local infrastructure over mocks when behavior depends on the real system. Useful options include PostgreSQL, Redis, Kafka or Redpanda, RabbitMQ, NATS, MinIO, OpenSearch, and similar services available through testcontainers.","","Before using testcontainers, check whether a functioning container runtime is available. Prefer `docker info`; if Docker is unavailable, check `podman info` and whether a compatible Docker API socket is configured. Finding the executable alone is not enough: verify the runtime can actually start containers. When a functioning runtime is available, testcontainers is an appropriate default for integration behavior that mocks cannot faithfully represent. Record the container-runtime requirement in the test documentation or final change summary.","","Use SQLite or DuckDB when they faithfully represent the tested contract. Do not use SQLite as evidence for PostgreSQL-specific SQL, transactions, locking, concurrency, extensions, or type behavior.","","Tests requiring real remote credentials or services such as Salesforce or Snowflake remain a user and project decision.","","When concurrency, retries, duplicate delivery, locking, or shared mutable state are real risks, add deterministic race-oriented tests where practical. Force relevant interleavings with barriers, events, controlled workers, or transactional locks rather than relying on sleeps. Assert atomicity, idempotency, ordering, uniqueness, and retry behavior as appropriate.","","Do not duplicate every assertion at unit, integration, and end-to-end levels. Each layer should prove a boundary that cheaper tests cannot prove faithfully.","","## Test Execution And Isolation","","Use the repository's established verification commands first. When pytest-xdist is installed and the relevant suite supports parallel execution, prefer:","","```bash","pytest -n auto","```","","Write new tests so they can execute independently whenever practical:","","- Use unique temporary paths, databases, schemas, ports, and resource names.","- Do not depend on test execution order.","- Isolate environment changes with fixtures such as monkeypatch.","- Avoid shared process-global mutation.","- Give each worker independent external state where concurrent access would alter the result.","- Make cleanup safe after both success and failure.","","When some tests genuinely require sequential execution, separate them from the parallel-safe suite. Run independent batches concurrently only when they do not share mutable resources. Otherwise run the required batches in sequence, while still using xdist inside each parallel-safe batch.","","If failures suggest broken isolation, rerun the failing tests sequentially and then rerun the relevant suite sequentially. A sequential pass does not make the problem acceptable: identify and correct the shared state, ordering dependency, port collision, database collision, or timing assumption where reasonable.",""]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
pub(crate) const MEMORY_SCHEMA_PREFIX: &str = "memory.";
|
|
2
|
+
pub(crate) const OPTION_TERMINATOR: &str = "--";
|
|
3
|
+
pub(crate) const MAP_SHORT_HELP: &str = "-h";
|
|
4
|
+
pub(crate) const LONG_OPTION_PREFIX: &str = "--";
|
|
5
|
+
pub(crate) const QUERY_FORMAT_LONG: &str = "long";
|
|
6
|
+
pub(crate) const QUERY_FORMAT_TABLE: &str = "table";
|
|
7
|
+
pub(crate) const QUERY_FORMAT_JSON: &str = "json";
|
|
8
|
+
pub(crate) const QUERY_FORMAT_CSV: &str = "csv";
|
|
9
|
+
pub(crate) const RELATION_KIND_TABLE: &str = "table";
|
|
10
|
+
pub(crate) const RELATION_KIND_VIEW: &str = "view";
|
|
11
|
+
pub(crate) const ARCHIVE_STATE_ARCHIVED: &str = "archived";
|
|
12
|
+
pub(crate) const RESOLUTION_STATUS_RESOLVED: &str = "resolved";
|
|
13
|
+
pub(crate) const DEFAULT_QUERY_LIMIT: usize = 20;
|
|
14
|
+
pub(crate) const MAX_QUERY_LIMIT: usize = 1000;
|
|
15
|
+
pub(crate) const MAP_USAGE: &str = "usage: fensu map [-h] [--direction {downstream}] [--depth DEPTH]\n [--root ROOTS] [--paths {absolute,relative,compact,none}]\n [--color {auto,always,never}] [--cache | --no-cache]\n [--cache-stats]\n symbol";
|
|
16
|
+
pub(crate) const MAP_HELP: &str = "usage: fensu map [-h] [--direction {downstream}] [--depth DEPTH]\n [--root ROOTS] [--paths {absolute,relative,compact,none}]\n [--color {auto,always,never}] [--cache | --no-cache]\n [--cache-stats]\n symbol\n\npositional arguments:\n symbol bare, dotted, or path::function project symbol\n\noptions:\n -h, --help show this help message and exit\n --direction {downstream}\n --depth DEPTH maximum call depth\n --root ROOTS Python import root to map; repeat for multiple roots\n --paths {absolute,relative,compact,none}\n path display style\n --color {auto,always,never}\n ANSI color behavior\n --cache enable map index caching\n --no-cache disable map index caching\n --cache-stats write map cache operation counts to stderr\n";
|
|
17
|
+
pub(crate) const DEFAULT_GRAPH_DEPTH: usize = 2;
|
|
18
|
+
pub(crate) const DEFAULT_GRAPH_NODES: usize = 50;
|
|
19
|
+
pub(crate) const DEFAULT_GRAPH_EDGES: usize = 100;
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
use crate::command::constants::{LONG_OPTION_PREFIX, MAP_SHORT_HELP, MAP_USAGE, OPTION_TERMINATOR};
|
|
2
|
+
use crate::mapping::models::{MapOptions, PathMode};
|
|
3
|
+
|
|
4
|
+
const LONG_OPTIONS: &[&str] = &[
|
|
5
|
+
"--help",
|
|
6
|
+
"--direction",
|
|
7
|
+
"--depth",
|
|
8
|
+
"--root",
|
|
9
|
+
"--paths",
|
|
10
|
+
"--color",
|
|
11
|
+
"--cache",
|
|
12
|
+
"--no-cache",
|
|
13
|
+
"--cache-stats",
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
pub(crate) fn parse(arguments: &[String]) -> Result<Option<MapOptions>, String> {
|
|
17
|
+
let mut symbol = None;
|
|
18
|
+
let mut depth = 3;
|
|
19
|
+
let mut roots = Vec::new();
|
|
20
|
+
let mut path_mode = PathMode::Relative;
|
|
21
|
+
let mut color = "auto".to_owned();
|
|
22
|
+
let mut cache_enabled = None;
|
|
23
|
+
let mut cache_stats = false;
|
|
24
|
+
let mut position = 0;
|
|
25
|
+
let mut options_ended = false;
|
|
26
|
+
while position < arguments.len() {
|
|
27
|
+
let argument = &arguments[position];
|
|
28
|
+
if !options_ended && argument == OPTION_TERMINATOR {
|
|
29
|
+
options_ended = true;
|
|
30
|
+
position += 1;
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
if options_ended {
|
|
34
|
+
if symbol.is_none() {
|
|
35
|
+
symbol = Some(argument.clone());
|
|
36
|
+
} else {
|
|
37
|
+
return Err(parser_error(&format!("unrecognized arguments: {argument}")));
|
|
38
|
+
}
|
|
39
|
+
position += 1;
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
let (name, inline) = argument
|
|
43
|
+
.split_once('=')
|
|
44
|
+
.map_or((argument.as_str(), None), |(name, value)| {
|
|
45
|
+
(name, Some(value))
|
|
46
|
+
});
|
|
47
|
+
let resolved = resolve_option(name)?;
|
|
48
|
+
match resolved {
|
|
49
|
+
"-h" | "--help" => return Ok(None),
|
|
50
|
+
"--direction" => {
|
|
51
|
+
let value = option_value(arguments, &mut position, resolved, inline)?;
|
|
52
|
+
choice(resolved, value, &["downstream"])?;
|
|
53
|
+
}
|
|
54
|
+
"--depth" => {
|
|
55
|
+
let value = option_value(arguments, &mut position, resolved, inline)?;
|
|
56
|
+
let parsed = value.parse::<i64>().map_err(|_| {
|
|
57
|
+
parser_error(&format!(
|
|
58
|
+
"argument --depth: invalid _nonnegative_int value: '{value}'"
|
|
59
|
+
))
|
|
60
|
+
})?;
|
|
61
|
+
if parsed < 0 {
|
|
62
|
+
return Err(parser_error(
|
|
63
|
+
"argument --depth: depth must be zero or greater",
|
|
64
|
+
));
|
|
65
|
+
}
|
|
66
|
+
depth =
|
|
67
|
+
usize::try_from(parsed).map_err(|error| parser_error(&error.to_string()))?;
|
|
68
|
+
}
|
|
69
|
+
"--root" => {
|
|
70
|
+
roots.push(option_value(arguments, &mut position, resolved, inline)?.to_owned())
|
|
71
|
+
}
|
|
72
|
+
"--paths" => {
|
|
73
|
+
let value = option_value(arguments, &mut position, resolved, inline)?;
|
|
74
|
+
choice(
|
|
75
|
+
resolved,
|
|
76
|
+
value,
|
|
77
|
+
&["absolute", "relative", "compact", "none"],
|
|
78
|
+
)?;
|
|
79
|
+
path_mode = match value {
|
|
80
|
+
"absolute" => PathMode::Absolute,
|
|
81
|
+
"compact" => PathMode::Compact,
|
|
82
|
+
"none" => PathMode::None,
|
|
83
|
+
_ => PathMode::Relative,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
"--color" => {
|
|
87
|
+
let value = option_value(arguments, &mut position, resolved, inline)?;
|
|
88
|
+
choice(resolved, value, &["auto", "always", "never"])?;
|
|
89
|
+
color = value.to_owned();
|
|
90
|
+
}
|
|
91
|
+
"--cache" => {
|
|
92
|
+
if cache_enabled == Some(false) {
|
|
93
|
+
return Err(parser_error(
|
|
94
|
+
"argument --cache: not allowed with argument --no-cache",
|
|
95
|
+
));
|
|
96
|
+
}
|
|
97
|
+
cache_enabled = Some(true);
|
|
98
|
+
}
|
|
99
|
+
"--no-cache" => {
|
|
100
|
+
if cache_enabled == Some(true) {
|
|
101
|
+
return Err(parser_error(
|
|
102
|
+
"argument --no-cache: not allowed with argument --cache",
|
|
103
|
+
));
|
|
104
|
+
}
|
|
105
|
+
cache_enabled = Some(false);
|
|
106
|
+
}
|
|
107
|
+
"--cache-stats" => cache_stats = true,
|
|
108
|
+
_ if resolved.starts_with('-') => {
|
|
109
|
+
return Err(parser_error(&format!("unrecognized arguments: {argument}")));
|
|
110
|
+
}
|
|
111
|
+
_ if symbol.is_none() => symbol = Some(argument.clone()),
|
|
112
|
+
_ => return Err(parser_error(&format!("unrecognized arguments: {argument}"))),
|
|
113
|
+
}
|
|
114
|
+
position += 1;
|
|
115
|
+
}
|
|
116
|
+
let symbol =
|
|
117
|
+
symbol.ok_or_else(|| parser_error("the following arguments are required: symbol"))?;
|
|
118
|
+
Ok(Some(MapOptions {
|
|
119
|
+
symbol,
|
|
120
|
+
depth,
|
|
121
|
+
roots,
|
|
122
|
+
path_mode,
|
|
123
|
+
color,
|
|
124
|
+
cache_enabled,
|
|
125
|
+
cache_stats,
|
|
126
|
+
}))
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
fn resolve_option(name: &str) -> Result<&str, String> {
|
|
130
|
+
if name == MAP_SHORT_HELP
|
|
131
|
+
|| !name.starts_with(LONG_OPTION_PREFIX)
|
|
132
|
+
|| LONG_OPTIONS.contains(&name)
|
|
133
|
+
{
|
|
134
|
+
return Ok(name);
|
|
135
|
+
}
|
|
136
|
+
let matches = LONG_OPTIONS
|
|
137
|
+
.iter()
|
|
138
|
+
.copied()
|
|
139
|
+
.filter(|option| option.starts_with(name))
|
|
140
|
+
.collect::<Vec<_>>();
|
|
141
|
+
match matches.as_slice() {
|
|
142
|
+
[resolved] => Ok(resolved),
|
|
143
|
+
[] => Ok(name),
|
|
144
|
+
_ => Err(parser_error(&format!(
|
|
145
|
+
"ambiguous option: {name} could match {}",
|
|
146
|
+
matches.join(", ")
|
|
147
|
+
))),
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
fn option_value<'a>(
|
|
152
|
+
arguments: &'a [String],
|
|
153
|
+
position: &mut usize,
|
|
154
|
+
name: &str,
|
|
155
|
+
inline: Option<&'a str>,
|
|
156
|
+
) -> Result<&'a str, String> {
|
|
157
|
+
if let Some(value) = inline {
|
|
158
|
+
return Ok(value);
|
|
159
|
+
}
|
|
160
|
+
*position += 1;
|
|
161
|
+
arguments
|
|
162
|
+
.get(*position)
|
|
163
|
+
.map(String::as_str)
|
|
164
|
+
.ok_or_else(|| parser_error(&format!("argument {name}: expected one argument")))
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
fn choice(name: &str, value: &str, choices: &[&str]) -> Result<(), String> {
|
|
168
|
+
if choices.contains(&value) {
|
|
169
|
+
Ok(())
|
|
170
|
+
} else {
|
|
171
|
+
Err(parser_error(&format!(
|
|
172
|
+
"argument {name}: invalid choice: '{value}' (choose from {})",
|
|
173
|
+
choices
|
|
174
|
+
.iter()
|
|
175
|
+
.map(|choice| format!("'{choice}'"))
|
|
176
|
+
.collect::<Vec<_>>()
|
|
177
|
+
.join(", ")
|
|
178
|
+
)))
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
fn parser_error(message: &str) -> String {
|
|
183
|
+
format!("{MAP_USAGE}\nfensu map: error: {message}")
|
|
184
|
+
}
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
use std::env;
|
|
2
|
+
use std::io::{self, IsTerminal};
|
|
3
|
+
use std::path::Path;
|
|
4
|
+
|
|
5
|
+
use fensu_memory::engine::main::archive_memory::archive_memory;
|
|
6
|
+
use fensu_memory::engine::main::check_memory::check_memory;
|
|
7
|
+
use fensu_memory::engine::main::memory_overview::memory_overview;
|
|
8
|
+
use fensu_memory::engine::main::memory_relation_schema::memory_relation_schema;
|
|
9
|
+
use fensu_memory::engine::main::memory_schema::memory_schema;
|
|
10
|
+
use fensu_memory::engine::main::query_memory_graph::query_memory_graph;
|
|
11
|
+
use fensu_memory::engine::main::query_memory_index::query_memory_index;
|
|
12
|
+
use fensu_memory::engine::main::rebuild_memory_index::rebuild_memory_index;
|
|
13
|
+
use fensu_memory::engine::main::sync_memory_index::sync_memory_index;
|
|
14
|
+
use fensu_memory::engine::models::{MemoryGraphQuery, MemoryQueryResult, SyncSummary};
|
|
15
|
+
use fensu_memory::source::main::bootstrap_memory::bootstrap_memory;
|
|
16
|
+
|
|
17
|
+
use crate::command::constants::{
|
|
18
|
+
MEMORY_SCHEMA_PREFIX, QUERY_FORMAT_CSV, QUERY_FORMAT_JSON, QUERY_FORMAT_TABLE,
|
|
19
|
+
};
|
|
20
|
+
use crate::command::helpers::{
|
|
21
|
+
memory_graph_rendering, memory_help, memory_human_rendering, memory_parsing,
|
|
22
|
+
memory_structured_rendering,
|
|
23
|
+
};
|
|
24
|
+
use crate::command::models::{ColorMode, MemoryCommand, MemoryProject};
|
|
25
|
+
use crate::configuration::main::load;
|
|
26
|
+
use crate::helpers::render;
|
|
27
|
+
use crate::models::{CliOutput, Fault};
|
|
28
|
+
|
|
29
|
+
pub(crate) fn execute_memory(arguments: &[String]) -> Result<CliOutput, String> {
|
|
30
|
+
let arguments = memory_parsing::normalize_options(arguments);
|
|
31
|
+
if memory_help::requested(&arguments) {
|
|
32
|
+
return Ok(CliOutput::success(memory_help::text(&arguments)));
|
|
33
|
+
}
|
|
34
|
+
let parsed = memory_parsing::parse(&arguments)?;
|
|
35
|
+
let color = use_color(parsed.color);
|
|
36
|
+
let project = resolve_project()?;
|
|
37
|
+
execute(parsed.command, &project, color)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
fn execute(
|
|
41
|
+
command: MemoryCommand,
|
|
42
|
+
project: &MemoryProject,
|
|
43
|
+
color: bool,
|
|
44
|
+
) -> Result<CliOutput, String> {
|
|
45
|
+
match command {
|
|
46
|
+
MemoryCommand::Summary => summarize(project, color),
|
|
47
|
+
MemoryCommand::Archive { paths, confirmed } => {
|
|
48
|
+
let result = archive_memory(
|
|
49
|
+
&project.repository_root,
|
|
50
|
+
&project.database_path,
|
|
51
|
+
&paths,
|
|
52
|
+
project.archive_after_days,
|
|
53
|
+
confirmed,
|
|
54
|
+
)
|
|
55
|
+
.map_err(|error| format!("Memory archive failed: {error}"))?;
|
|
56
|
+
Ok(CliOutput::success(memory_human_rendering::archive(
|
|
57
|
+
&result, color,
|
|
58
|
+
)))
|
|
59
|
+
}
|
|
60
|
+
MemoryCommand::Check => check(project, color),
|
|
61
|
+
MemoryCommand::Sync => {
|
|
62
|
+
let summary = sync(project)?;
|
|
63
|
+
Ok(CliOutput::success(memory_human_rendering::sync(
|
|
64
|
+
&summary,
|
|
65
|
+
&project.repository_root,
|
|
66
|
+
&project.database_path,
|
|
67
|
+
false,
|
|
68
|
+
color,
|
|
69
|
+
)))
|
|
70
|
+
}
|
|
71
|
+
MemoryCommand::Rebuild => {
|
|
72
|
+
let summary = rebuild_memory_index(&project.repository_root, &project.database_path)
|
|
73
|
+
.map_err(|error| format!("Memory rebuild failed: {error}"))?;
|
|
74
|
+
Ok(CliOutput::success(memory_human_rendering::rebuild(
|
|
75
|
+
&summary,
|
|
76
|
+
&project.repository_root,
|
|
77
|
+
&project.database_path,
|
|
78
|
+
color,
|
|
79
|
+
)))
|
|
80
|
+
}
|
|
81
|
+
MemoryCommand::Schema { relation } => schema(relation.as_deref(), color),
|
|
82
|
+
MemoryCommand::Graph { query, format } => graph(project, &query, &format, color),
|
|
83
|
+
MemoryCommand::Sql {
|
|
84
|
+
query,
|
|
85
|
+
limit,
|
|
86
|
+
format,
|
|
87
|
+
} => sql(project, &query, limit, &format, color),
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
fn summarize(project: &MemoryProject, color: bool) -> Result<CliOutput, String> {
|
|
92
|
+
let summary = sync(project)?;
|
|
93
|
+
let overview = memory_overview(&project.database_path)
|
|
94
|
+
.map_err(|error| format!("Memory overview failed: {error}"))?;
|
|
95
|
+
let mut output = memory_human_rendering::sync(
|
|
96
|
+
&summary,
|
|
97
|
+
&project.repository_root,
|
|
98
|
+
&project.database_path,
|
|
99
|
+
true,
|
|
100
|
+
color,
|
|
101
|
+
);
|
|
102
|
+
output.push_str(&memory_human_rendering::overview(&overview, color));
|
|
103
|
+
Ok(CliOutput::success(output))
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
fn check(project: &MemoryProject, color: bool) -> Result<CliOutput, String> {
|
|
107
|
+
let result = check_memory(&project.repository_root, &project.database_path)
|
|
108
|
+
.map_err(|error| format!("Memory check failed: {error}"))?;
|
|
109
|
+
let faults = result
|
|
110
|
+
.diagnostics
|
|
111
|
+
.iter()
|
|
112
|
+
.map(|diagnostic| Fault {
|
|
113
|
+
code: diagnostic.code.to_owned(),
|
|
114
|
+
path: project
|
|
115
|
+
.repository_root
|
|
116
|
+
.join(&diagnostic.repository_relative_path)
|
|
117
|
+
.to_string_lossy()
|
|
118
|
+
.into_owned(),
|
|
119
|
+
line: diagnostic.line.and_then(|value| u32::try_from(value).ok()),
|
|
120
|
+
column: diagnostic
|
|
121
|
+
.column
|
|
122
|
+
.and_then(|value| u32::try_from(value).ok()),
|
|
123
|
+
message: diagnostic.message.clone(),
|
|
124
|
+
remediation: Some(diagnostic.remediation.to_owned()),
|
|
125
|
+
warning: false,
|
|
126
|
+
})
|
|
127
|
+
.collect::<Vec<_>>();
|
|
128
|
+
let stdout = render::report(render::ReportRequest {
|
|
129
|
+
faults: &faults,
|
|
130
|
+
warnings: &[],
|
|
131
|
+
root: &project.repository_root,
|
|
132
|
+
color,
|
|
133
|
+
show_warnings: false,
|
|
134
|
+
evaluation_summary: None,
|
|
135
|
+
applied_exceptions: 0,
|
|
136
|
+
threshold_uses: &[],
|
|
137
|
+
});
|
|
138
|
+
Ok(CliOutput {
|
|
139
|
+
stdout,
|
|
140
|
+
stderr: String::new(),
|
|
141
|
+
exit_code: i32::from(!faults.is_empty()),
|
|
142
|
+
})
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
fn schema(relation: Option<&str>, color: bool) -> Result<CliOutput, String> {
|
|
146
|
+
if let Some(name) = relation {
|
|
147
|
+
let qualified = if name.starts_with(MEMORY_SCHEMA_PREFIX) {
|
|
148
|
+
name.to_owned()
|
|
149
|
+
} else {
|
|
150
|
+
format!("{MEMORY_SCHEMA_PREFIX}{name}")
|
|
151
|
+
};
|
|
152
|
+
let relation = memory_relation_schema(&qualified)
|
|
153
|
+
.ok_or_else(|| format!("Unknown memory relation: {qualified}"))?;
|
|
154
|
+
return Ok(CliOutput::success(memory_human_rendering::relation(
|
|
155
|
+
&relation, color,
|
|
156
|
+
)));
|
|
157
|
+
}
|
|
158
|
+
Ok(CliOutput::success(memory_human_rendering::schema(
|
|
159
|
+
&memory_schema(),
|
|
160
|
+
color,
|
|
161
|
+
)))
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
fn graph(
|
|
165
|
+
project: &MemoryProject,
|
|
166
|
+
query: &MemoryGraphQuery,
|
|
167
|
+
format: &str,
|
|
168
|
+
color: bool,
|
|
169
|
+
) -> Result<CliOutput, String> {
|
|
170
|
+
let summary = sync(project)?;
|
|
171
|
+
let result = query_memory_graph(&project.database_path, query)
|
|
172
|
+
.map_err(|error| format!("Memory graph failed: {error}"))?;
|
|
173
|
+
let machine = format == QUERY_FORMAT_JSON;
|
|
174
|
+
let stdout = if machine {
|
|
175
|
+
memory_structured_rendering::graph_json(&result, query)
|
|
176
|
+
} else {
|
|
177
|
+
memory_graph_rendering::graph(&result, query, color)
|
|
178
|
+
};
|
|
179
|
+
Ok(CliOutput {
|
|
180
|
+
stdout,
|
|
181
|
+
stderr: memory_human_rendering::sync(
|
|
182
|
+
&summary,
|
|
183
|
+
&project.repository_root,
|
|
184
|
+
&project.database_path,
|
|
185
|
+
true,
|
|
186
|
+
color && !machine,
|
|
187
|
+
),
|
|
188
|
+
exit_code: 0,
|
|
189
|
+
})
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
fn sql(
|
|
193
|
+
project: &MemoryProject,
|
|
194
|
+
query: &str,
|
|
195
|
+
limit: usize,
|
|
196
|
+
format: &str,
|
|
197
|
+
color: bool,
|
|
198
|
+
) -> Result<CliOutput, String> {
|
|
199
|
+
let summary = sync(project)?;
|
|
200
|
+
let result = query_memory_index(&project.database_path, query, limit)
|
|
201
|
+
.map_err(|error| format!("Memory query failed: {error}"))?;
|
|
202
|
+
let human = format != QUERY_FORMAT_JSON && format != QUERY_FORMAT_CSV;
|
|
203
|
+
Ok(CliOutput {
|
|
204
|
+
stdout: render_query(&result, format, color && human),
|
|
205
|
+
stderr: memory_human_rendering::sync(
|
|
206
|
+
&summary,
|
|
207
|
+
&project.repository_root,
|
|
208
|
+
&project.database_path,
|
|
209
|
+
true,
|
|
210
|
+
color && human,
|
|
211
|
+
),
|
|
212
|
+
exit_code: 0,
|
|
213
|
+
})
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
fn render_query(result: &MemoryQueryResult, format: &str, color: bool) -> String {
|
|
217
|
+
match format {
|
|
218
|
+
QUERY_FORMAT_JSON => memory_structured_rendering::query_json(result),
|
|
219
|
+
QUERY_FORMAT_CSV => memory_structured_rendering::query_csv(result),
|
|
220
|
+
QUERY_FORMAT_TABLE => memory_human_rendering::query_table(result, color),
|
|
221
|
+
_ => memory_human_rendering::query_long(result, color),
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
fn sync(project: &MemoryProject) -> Result<SyncSummary, String> {
|
|
226
|
+
sync_memory_index(&project.repository_root, &project.database_path)
|
|
227
|
+
.map_err(|error| format!("Memory sync failed: {error}"))
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
fn resolve_project() -> Result<MemoryProject, String> {
|
|
231
|
+
let (source_path, loaded) = load::load(Path::new("."))?;
|
|
232
|
+
let repository_root = source_path
|
|
233
|
+
.parent()
|
|
234
|
+
.ok_or_else(|| "Fensu configuration has no repository directory.".to_owned())?
|
|
235
|
+
.to_path_buf();
|
|
236
|
+
if !loaded.memory_enabled {
|
|
237
|
+
return Err(
|
|
238
|
+
"Fensu Memory is disabled; set experimental.memory = true in the project configuration."
|
|
239
|
+
.to_owned(),
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
bootstrap_memory(&repository_root)?;
|
|
243
|
+
let database_path = repository_root.join(".fensu/memory/memory.sqlite3");
|
|
244
|
+
Ok(MemoryProject {
|
|
245
|
+
repository_root,
|
|
246
|
+
database_path,
|
|
247
|
+
archive_after_days: loaded.memory_archive_after_days,
|
|
248
|
+
})
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
fn use_color(mode: ColorMode) -> bool {
|
|
252
|
+
env::var_os("NO_COLOR").is_none()
|
|
253
|
+
&& (mode == ColorMode::Always || mode == ColorMode::Auto && io::stdout().is_terminal())
|
|
254
|
+
}
|