-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add QA command and knowledge capture with Ollama integration #93
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
- Add `know qa` command for running pint, tests, and PHPStan with AI fix suggestions - Add `know capture` command for automatic insight extraction from conversation context - Add OllamaService for LLM-powered analysis - Fix type safety issues in QdrantService search/scroll methods - Clean up phpstan baseline after resolving errors - Improve MarkdownExporter with proper type handling Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
📝 WalkthroughWalkthroughThis PR introduces automated knowledge capture and QA orchestration with Ollama integration, adds defensive type checking across multiple commands and services, and consolidates configuration handling with improved null-safety throughout the codebase. Changes
Sequence DiagramssequenceDiagram
participant User
participant KCC as KnowledgeCaptureCommand
participant Detector as Pattern Detector
participant Ollama as OllamaService
participant Qdrant as QdrantService
User->>KCC: Execute with context (--context, --file, --session, --project)
KCC->>KCC: Gather context from options/file/stdin
KCC->>KCC: Filter noise, detect patterns
KCC->>Detector: Analyze for artifacts (insights, blockers, decisions)
Detector-->>KCC: Detection result with type/category
KCC->>Qdrant: Check for existing entry (deduplication)
Qdrant-->>KCC: Duplicate status
alt Duplicate found
KCC->>User: Skip (already captured)
else New entry
KCC->>Ollama: Extract structured insight (title, content, tags)
Ollama-->>KCC: Structured insight or fallback
KCC->>Qdrant: Upsert knowledge entry with session/project tags
Qdrant-->>KCC: Entry persisted with ID
KCC->>User: Confirm capture (or show dry-run preview)
end
sequenceDiagram
participant User
participant QA as QaCommand
participant Pint as Pint
participant Tests as Pest Tests
participant PHPStan as PHPStan
participant Ollama as OllamaService
User->>QA: Execute with --fix, --all, --skip-* options
QA->>Pint: Run Pint linting (priority 1)
alt Pint fails
Pint-->>QA: Output with issues
QA->>QA: Extract first issue
QA->>Ollama: Get AI suggestion (if not --no-ai)
Ollama-->>QA: Suggestion or fallback
QA->>User: Report issue with suggestion
end
alt Pint succeeds
QA->>Tests: Run Pest tests (priority 2)
alt Tests fail
Tests-->>QA: Test output
QA->>QA: Extract test failure
QA->>Ollama: Generate suggestion
Ollama-->>QA: AI-generated guidance
QA->>User: Report test failure with suggestion
end
alt Tests succeed
QA->>PHPStan: Run PHPStan analysis (priority 3)
PHPStan-->>QA: Analysis output (if issues)
alt PHPStan issues found
QA->>Ollama: Suggest fix for static analysis issue
Ollama-->>QA: AI suggestion
QA->>User: Report PHPStan issue with suggestion
else All checks pass
QA->>User: All QA checks passed ✓
end
end
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related issues
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
📊 Coverage Report
Files Below Threshold
🏆 Synapse Sentinel Gate |
🔧 Synapse Sentinel: 1 check need attentionThe following issues must be resolved before this PR can be merged: All tests passed.--- Quick Reference:
🤖 Generated by Synapse Sentinel - View Run |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
🤖 Fix all issues with AI agents
In `@app/Commands/KnowledgeCaptureCommand.php`:
- Line 176: The assignment setting 'id' => (string) uuid_create() in
KnowledgeCaptureCommand should use Laravel's UUID helper for portability—replace
uuid_create() with Str::uuid()->toString() (remove the explicit (string) cast as
toString returns a string) and ensure Illuminate\Support\Str is imported at the
top of the class if not already present; update the 'id' array value and import
to match other commands like SyncCommand and KnowledgeAddCommand.
In `@app/Commands/KnowledgeListCommand.php`:
- Around line 67-71: The map callback for $results->map accesses $entry['tags']
without a PHPStan-friendly guard; update the anonymous function (the
$results->map callback that builds $rows) to first ensure $entry['tags'] exists
and is an array (e.g. $tagsArray = isset($entry['tags']) &&
is_array($entry['tags']) ? $entry['tags'] : []), then use $tagsArray for
count(), array_slice() and implode so all array access is explicitly
type-checked and PHPStan level 8 is satisfied.
In `@app/Commands/KnowledgeSearchCommand.php`:
- Around line 43-44: Remove the dead local variable $useSemantic in the
KnowledgeSearchCommand: the assignment $useSemantic = $this->option('semantic')
is unused and flagged by static analysis, so delete that line (or, if you intend
to implement the semantic flag, wire $this->option('semantic') into the command
logic where appropriate). Ensure the command signature and option handling
remain consistent (either remove the --semantic option from the signature if not
implemented, or use the retrieved value inside the handle/execute method to
affect behavior).
In `@app/Commands/QaCommand.php`:
- Line 20: The CLI option default for PHPStan level in QaCommand is set to 9 but
the project standard is 8; update the option definition (the {--level=9 :
PHPStan level (default: 9)} entry) in the QaCommand class so the default value
becomes 8 (i.e., change the level option default to 8) and ensure any related
help text or docstring that mentions the default is updated to reflect level 8.
- Around line 170-177: The variable $suggestion can be uninitialized if the
closure passed to $this->task isn't executed or fails; initialize $suggestion
(e.g., $suggestion = '' or null) before the $this->task call or ensure you check
isset/empty before using it in $this->line, and keep the closure calling
$this->getAiSuggestion($type, $firstIssue) intact so it still assigns by
reference; update references to $suggestion (in the closure and in $this->line)
to rely on the initialized value or a safe fallback.
In `@app/Services/MarkdownExporter.php`:
- Around line 30-38: The id value is being discarded when numeric because
getString only returns strings; update the $id assignment to preserve numeric
IDs by checking isset($entry['id']) && is_numeric($entry['id']) and casting to
string when true, otherwise fall back to $this->getString($entry, 'id'); apply
the same pattern for any other fields that may be numeric but are currently
using getString (e.g., the front-matter field referenced as created_at if
needed) so numeric values are converted to strings rather than becoming empty.
In `@config/search.php`:
- Line 66: The fallback model default was changed to 'mistral:7b' in
config/search.php but KnowledgeSearchCommand and QaCommand still hardcode
'llama3.2:3b', causing inconsistent behavior compared to
KnowledgeCaptureCommand; update the fallback/default model string in
KnowledgeSearchCommand and QaCommand to 'mistral:7b' (match
KnowledgeCaptureCommand and config) so all commands use the same OLLAMA_MODEL
fallback when the environment variable is unset.
🧹 Nitpick comments (9)
app/Commands/InstallCommand.php (1)
23-24: Avoid redundant option retrieval.The
$this->option('project')is called twice. Consider storing it once for efficiency.♻️ Suggested improvement
- /** `@var` string $project */ - $project = is_string($this->option('project')) ? $this->option('project') : 'default'; + $optionValue = $this->option('project'); + $project = is_string($optionValue) ? $optionValue : 'default';app/Services/QdrantService.php (1)
375-375: Inconsistent tags array filtering ingetById.Unlike
search(line 228) andscroll(line 299), which filter the tags array to ensure all elements are strings,getByIdreturns the raw array without filtering.♻️ Proposed fix for consistency
- 'tags' => is_array($payload['tags'] ?? null) ? $payload['tags'] : [], + 'tags' => is_array($payload['tags'] ?? null) ? array_values(array_filter($payload['tags'], fn ($tag): bool => is_string($tag))) : [],app/Services/OllamaService.php (2)
15-27: Consider adding HTTPS support for secure Ollama deployments.The base URI is hardcoded to
http://. For production deployments where Ollama runs behind a reverse proxy with TLS, this would require a protocol parameter or auto-detection.♻️ Optional: Add secure option
public function __construct( string $host = 'localhost', int $port = 11434, string $model = 'llama3.2:3b', int $timeout = 30, + bool $secure = false, ) { $this->model = $model; + $protocol = $secure ? 'https' : 'http'; $this->client = new Client([ - 'base_uri' => "http://{$host}:{$port}", + 'base_uri' => "{$protocol}://{$host}:{$port}", 'timeout' => $timeout, 'connect_timeout' => 5, 'http_errors' => false, ]); }
78-80: Silent error handling may hinder debugging.Catching all
Throwableand returning an empty string provides graceful degradation, but completely swallowing exceptions (including connection errors, timeouts, etc.) makes it difficult to diagnose issues. Consider adding logging.♻️ Optional: Add error logging
- } catch (\Throwable) { + } catch (\Throwable $e) { + // Log for debugging while still gracefully degrading + logger()->debug('Ollama request failed', ['error' => $e->getMessage()]); return ''; }app/Commands/KnowledgeCaptureCommand.php (2)
212-219: Non-blocking stdin read may still loop indefinitely.Setting
stream_set_blocking(STDIN, false)and then looping withfgets()could behave unexpectedly in interactive terminals. When stdin is a TTY, non-blocking reads may return false immediately or loop. Consider adding a safeguard.♻️ Proposed fix with TTY check
// Try reading from stdin (non-blocking) + if (posix_isatty(STDIN)) { + return ''; + } + $stdin = ''; stream_set_blocking(STDIN, false); while (($line = fgets(STDIN)) !== false) { $stdin .= $line; } return trim($stdin);
273-283: Consider extracting OllamaService instantiation to reduce duplication.The OllamaService instantiation with config reading is duplicated across
KnowledgeCaptureCommand,KnowledgeSearchCommand, andQaCommand. Consider registering it in the service provider or creating a factory method.app/Commands/KnowledgeSearchCommand.php (1)
129-129: Inconsistent default model across commands.
KnowledgeSearchCommanddefaults to'llama3.2:3b'whileKnowledgeCaptureCommand(line 281) defaults to'mistral:7b'. This inconsistency could cause confusion.Consider using a consistent default model across all commands, ideally defined in the config file as a single source of truth.
app/Providers/AppServiceProvider.php (1)
36-74: Consider registering OllamaService in the service provider.
OllamaServiceis instantiated directly in multiple commands (KnowledgeCaptureCommand,KnowledgeSearchCommand,QaCommand) with duplicated config reading logic. Registering it as a singleton would centralize the configuration and reduce duplication.♻️ Proposed addition to register()
// Ollama LLM service $this->app->singleton(OllamaService::class, function () { /** `@var` array<string, mixed> $config */ $config = config('search.ollama', []); return new \App\Services\OllamaService( host: is_string($config['host'] ?? null) ? $config['host'] : 'localhost', port: is_int($config['port'] ?? null) ? $config['port'] : 11434, model: is_string($config['model'] ?? null) ? $config['model'] : 'mistral:7b', timeout: is_int($config['timeout'] ?? null) ? $config['timeout'] : 30, ); });app/Commands/QaCommand.php (1)
101-118: Inconsistent path handling between check types.Pint uses absolute paths (
$projectRoot.'/vendor/bin/pint'), while PHPStan uses a relative path ('vendor/bin/phpstan'). This inconsistency could cause issues depending on the working directory.♻️ Proposed fix for consistency
private function buildPhpstanProcess(): Process { /** `@var` int|string $level */ $level = $this->option('level'); $level = is_numeric($level) ? (int) $level : 9; $args = [ - 'vendor/bin/phpstan', + base_path('vendor/bin/phpstan'), 'analyse', '--level='.$level, '--no-progress', '--error-format=raw', ]; if (file_exists(base_path('phpstan.neon'))) { - $args[] = '--configuration='.base_path('phpstan.neon'); + $args[] = '--configuration=phpstan.neon'; } return new Process($args, base_path()); }Also applies to: 126-138
|
|
||
| /** @var array{id: string, title: string, content: string, tags: array<string>, category: string, priority: string, source: string, confidence: int, module?: string} $entry */ | ||
| $entry = [ | ||
| 'id' => (string) uuid_create(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check uuid_create usage
echo "=== Checking uuid_create() usage ==="
rg -n 'uuid_create' --type=php
# Check for alternative UUID implementations
echo -e "\n=== Checking for Ramsey UUID usage ==="
rg -n 'Ramsey\\Uuid|uuid4|UUID' --type=php
# Check for Laravel Str::uuid usage
echo -e "\n=== Checking for Laravel Str::uuid usage ==="
rg -n 'Str::uuid' --type=php
# Check composer.json for dependencies
echo -e "\n=== Checking composer.json ==="
cat composer.json | grep -A 50 '"require"'Repository: conduit-ui/knowledge
Length of output: 2673
🏁 Script executed:
#!/bin/bash
# Get the full context of the KnowledgeCaptureCommand.php file to understand uuid_create usage
echo "=== Checking the specific file ==="
head -200 app/Commands/KnowledgeCaptureCommand.php | tail -50Repository: conduit-ui/knowledge
Length of output: 1770
🏁 Script executed:
#!/bin/bash
# Check if there are any imports or use statements for UUID-related classes
rg -n 'use.*Uuid|use.*UUID|function uuid_create' --type=php --max-count=20Repository: conduit-ui/knowledge
Length of output: 274
Use Str::uuid()->toString() instead of uuid_create().
uuid_create() is from the PECL uuid extension, which is not listed in project dependencies. Other commands in this codebase (SyncCommand, KnowledgeAddCommand) already use Str::uuid()->toString() for consistency and portability.
🤖 Prompt for AI Agents
In `@app/Commands/KnowledgeCaptureCommand.php` at line 176, The assignment setting
'id' => (string) uuid_create() in KnowledgeCaptureCommand should use Laravel's
UUID helper for portability—replace uuid_create() with Str::uuid()->toString()
(remove the explicit (string) cast as toString returns a string) and ensure
Illuminate\Support\Str is imported at the top of the class if not already
present; update the 'id' array value and import to match other commands like
SyncCommand and KnowledgeAddCommand.
| /** @var array<int, array<int, string>> $rows */ | ||
| $rows = $results->map(function (array $entry): array { | ||
| $tags = count($entry['tags']) > 0 | ||
| ? implode(', ', array_slice($entry['tags'], 0, 3)).(count($entry['tags']) > 3 ? '...' : '') | ||
| : '-'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
# First, let's check the file exists and read the relevant section
cat -n app/Commands/KnowledgeListCommand.php | sed -n '60,80p'Repository: conduit-ui/knowledge
Length of output: 184
🏁 Script executed:
# Also get the full function to understand the context better
cat -n app/Commands/KnowledgeListCommand.phpRepository: conduit-ui/knowledge
Length of output: 3669
🏁 Script executed:
find . -name "QdrantService.php" -o -name "*qdrant*" -type f | head -20Repository: conduit-ui/knowledge
Length of output: 141
🏁 Script executed:
# Search for QdrantService definition
rg "class QdrantService" -A 30Repository: conduit-ui/knowledge
Length of output: 2079
🏁 Script executed:
# Look for the scroll method specifically
rg "public function scroll" -A 50Repository: conduit-ui/knowledge
Length of output: 4057
Add type guard for $entry['tags'] to satisfy PHPStan level 8 strict analysis.
While QdrantService guarantees tags is always an array, PHPStan level 8 strict rules require explicit type guards for array key access on generic array types. Line 69 accesses $entry['tags'] without proving the key exists or the value is an array to the static analyzer.
Suggested fix
- $rows = $results->map(function (array $entry): array {
- $tags = count($entry['tags']) > 0
- ? implode(', ', array_slice($entry['tags'], 0, 3)).(count($entry['tags']) > 3 ? '...' : '')
- : '-';
+ $rows = $results->map(function (array $entry): array {
+ $tagsList = is_array($entry['tags'] ?? null) ? $entry['tags'] : [];
+ $tags = count($tagsList) > 0
+ ? implode(', ', array_slice($tagsList, 0, 3)).(count($tagsList) > 3 ? '...' : '')
+ : '-';📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| /** @var array<int, array<int, string>> $rows */ | |
| $rows = $results->map(function (array $entry): array { | |
| $tags = count($entry['tags']) > 0 | |
| ? implode(', ', array_slice($entry['tags'], 0, 3)).(count($entry['tags']) > 3 ? '...' : '') | |
| : '-'; | |
| /** `@var` array<int, array<int, string>> $rows */ | |
| $rows = $results->map(function (array $entry): array { | |
| $tagsList = is_array($entry['tags'] ?? null) ? $entry['tags'] : []; | |
| $tags = count($tagsList) > 0 | |
| ? implode(', ', array_slice($tagsList, 0, 3)).(count($tagsList) > 3 ? '...' : '') | |
| : '-'; |
🤖 Prompt for AI Agents
In `@app/Commands/KnowledgeListCommand.php` around lines 67 - 71, The map callback
for $results->map accesses $entry['tags'] without a PHPStan-friendly guard;
update the anonymous function (the $results->map callback that builds $rows) to
first ensure $entry['tags'] exists and is an array (e.g. $tagsArray =
isset($entry['tags']) && is_array($entry['tags']) ? $entry['tags'] : []), then
use $tagsArray for count(), array_slice() and implode so all array access is
explicitly type-checked and PHPStan level 8 is satisfied.
| $useSemantic = $this->option('semantic'); | ||
| $summarize = $this->option('summarize'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove unused $useSemantic variable.
The $useSemantic variable is assigned but never used, as flagged by static analysis.
🔧 Proposed fix
$previewLength = (int) $this->option('preview-length');
- $useSemantic = $this->option('semantic');
$summarize = $this->option('summarize');Additionally, if the --semantic option is intended for future use, consider removing it from the signature until it's implemented, or implement the feature.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| $useSemantic = $this->option('semantic'); | |
| $summarize = $this->option('summarize'); | |
| $previewLength = (int) $this->option('preview-length'); | |
| $summarize = $this->option('summarize'); |
🧰 Tools
🪛 PHPMD (2.15.0)
43-43: Avoid unused local variables such as '$useSemantic'. (undefined)
(UnusedLocalVariable)
🤖 Prompt for AI Agents
In `@app/Commands/KnowledgeSearchCommand.php` around lines 43 - 44, Remove the
dead local variable $useSemantic in the KnowledgeSearchCommand: the assignment
$useSemantic = $this->option('semantic') is unused and flagged by static
analysis, so delete that line (or, if you intend to implement the semantic flag,
wire $this->option('semantic') into the command logic where appropriate). Ensure
the command signature and option handling remain consistent (either remove the
--semantic option from the signature if not implemented, or use the retrieved
value inside the handle/execute method to affect behavior).
| {--fix : Auto-fix code style issues with Pint} | ||
| {--all : Show all issues instead of just the first} | ||
| {--raw : Show raw error without AI processing} | ||
| {--level=9 : PHPStan level (default: 9)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PHPStan level default differs from coding guidelines.
The default PHPStan level is set to 9, but the coding guidelines specify level 8. Consider aligning the default with the project standard.
🔧 Proposed fix
- {--level=9 : PHPStan level (default: 9)}
+ {--level=8 : PHPStan level (default: 8)}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| {--level=9 : PHPStan level (default: 9)} | |
| {--level=8 : PHPStan level (default: 8)} |
🤖 Prompt for AI Agents
In `@app/Commands/QaCommand.php` at line 20, The CLI option default for PHPStan
level in QaCommand is set to 9 but the project standard is 8; update the option
definition (the {--level=9 : PHPStan level (default: 9)} entry) in the QaCommand
class so the default value becomes 8 (i.e., change the level option default to
8) and ensure any related help text or docstring that mentions the default is
updated to reflect level 8.
| $this->task('AI suggestion', function () use ($type, $firstIssue, &$suggestion): bool { | ||
| $suggestion = $this->getAiSuggestion($type, $firstIssue); | ||
|
|
||
| return $suggestion !== ''; | ||
| }); | ||
|
|
||
| $this->newLine(); | ||
| $this->line($suggestion ?? $firstIssue); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential uninitialized variable $suggestion.
The $suggestion variable is set by reference inside the closure, but if the closure isn't executed or fails before assignment, $suggestion would be uninitialized when used on line 177.
🔧 Proposed fix
+ $suggestion = '';
+
// Default: Get AI suggestion
$this->task('AI suggestion', function () use ($type, $firstIssue, &$suggestion): bool {
$suggestion = $this->getAiSuggestion($type, $firstIssue);
return $suggestion !== '';
});
$this->newLine();
- $this->line($suggestion ?? $firstIssue);
+ $this->line($suggestion !== '' ? $suggestion : $firstIssue);🤖 Prompt for AI Agents
In `@app/Commands/QaCommand.php` around lines 170 - 177, The variable $suggestion
can be uninitialized if the closure passed to $this->task isn't executed or
fails; initialize $suggestion (e.g., $suggestion = '' or null) before the
$this->task call or ensure you check isset/empty before using it in $this->line,
and keep the closure calling $this->getAiSuggestion($type, $firstIssue) intact
so it still assigns by reference; update references to $suggestion (in the
closure and in $this->line) to rely on the initialized value or a safe fallback.
| $id = $this->getString($entry, 'id'); | ||
| $title = $this->getString($entry, 'title'); | ||
| $category = $this->getString($entry, 'category'); | ||
| $module = $this->getString($entry, 'module'); | ||
| $priority = $this->getString($entry, 'priority'); | ||
| $confidence = is_numeric($entry['confidence'] ?? null) ? $entry['confidence'] : 0; | ||
| $status = $this->getString($entry, 'status'); | ||
| $usageCount = is_numeric($entry['usage_count'] ?? null) ? $entry['usage_count'] : 0; | ||
| $createdAt = $this->getString($entry, 'created_at'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
find . -name "MarkdownExporter.php" -type fRepository: conduit-ui/knowledge
Length of output: 99
🏁 Script executed:
cat -n app/Services/MarkdownExporter.phpRepository: conduit-ui/knowledge
Length of output: 3563
Preserve numeric IDs in front matter.
getString only accepts strings; numeric IDs (common in systems like Qdrant) are converted to empty strings, resulting in id: (missing value) in the YAML output (line 30, 42). This is inconsistent with how confidence and usageCount are handled (lines 35, 37), which preserve numeric values. Numeric IDs should be converted to strings instead of being discarded.
Suggested fix
private function getString(array $entry, string $key): string
{
$value = $entry[$key] ?? null;
- return is_string($value) ? $value : '';
+ if (is_string($value)) {
+ return $value;
+ }
+
+ if (is_int($value) || is_float($value)) {
+ return (string) $value;
+ }
+
+ if ($value instanceof \Stringable) {
+ return (string) $value;
+ }
+
+ return '';
}🧰 Tools
🪛 PHPStan (2.1.33)
Ignored error pattern #^Construct empty() is not allowed. Use more strict comparison.$# in path /home/jailuser/git/app/Services/MarkdownExporter.php was not matched in reported errors.
(ignore.unmatched)
🤖 Prompt for AI Agents
In `@app/Services/MarkdownExporter.php` around lines 30 - 38, The id value is
being discarded when numeric because getString only returns strings; update the
$id assignment to preserve numeric IDs by checking isset($entry['id']) &&
is_numeric($entry['id']) and casting to string when true, otherwise fall back to
$this->getString($entry, 'id'); apply the same pattern for any other fields that
may be numeric but are currently using getString (e.g., the front-matter field
referenced as created_at if needed) so numeric values are converted to strings
rather than becoming empty.
| 'host' => env('OLLAMA_HOST', 'localhost'), | ||
| 'port' => env('OLLAMA_PORT', 11434), | ||
| 'model' => env('OLLAMA_MODEL', 'llama3.2:3b'), | ||
| 'model' => env('OLLAMA_MODEL', 'mistral:7b'), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Search for OllamaService and check for model defaults
find . -name "OllamaService.php" -type fRepository: conduit-ui/knowledge
Length of output: 184
🏁 Script executed:
#!/bin/bash
# Check OllamaService for hardcoded model references
rg -n "mistral|llama|model" --type php app/Services/ 2>/dev/null | head -50Repository: conduit-ui/knowledge
Length of output: 463
🏁 Script executed:
#!/bin/bash
# View the actual config/search.php file to understand context
cat -n config/search.phpRepository: conduit-ui/knowledge
Length of output: 3175
🏁 Script executed:
#!/bin/bash
# Find where OllamaService is instantiated
rg -n "OllamaService" --type php -B 2 -A 2 | head -80Repository: conduit-ui/knowledge
Length of output: 6255
🏁 Script executed:
#!/bin/bash
# Check for service providers or container bindings
find . -name "*.php" -path "*/app/*" -type f -exec grep -l "OllamaService" {} \;Repository: conduit-ui/knowledge
Length of output: 210
🏁 Script executed:
#!/bin/bash
# Check the commands that use OllamaService
cat -n app/Commands/KnowledgeCaptureCommand.php | grep -A 5 -B 5 "OllamaService"Repository: conduit-ui/knowledge
Length of output: 995
🏁 Script executed:
#!/bin/bash
# Check all three commands for OllamaService usage
for file in app/Commands/KnowledgeCaptureCommand.php app/Commands/KnowledgeSearchCommand.php app/Commands/QaCommand.php; do
echo "=== $file ==="
rg -n "OllamaService|new |function " "$file" -A 2 | head -40
doneRepository: conduit-ui/knowledge
Length of output: 3465
🏁 Script executed:
#!/bin/bash
# Check if there's a service provider that binds OllamaService with config
find . -name "*Provider.php" -type f -path "*/app/*" -exec grep -l "OllamaService\|ollama" {} \;Repository: conduit-ui/knowledge
Length of output: 46
🏁 Script executed:
#!/bin/bash
# Check if OllamaService is instantiated anywhere else without explicit model parameter
rg -n "new OllamaService" --type php -A 5Repository: conduit-ui/knowledge
Length of output: 1943
🏁 Script executed:
#!/bin/bash
# Check the full instantiation in KnowledgeSearchCommand
cat -n app/Commands/KnowledgeSearchCommand.php | sed -n '121,135p'Repository: conduit-ui/knowledge
Length of output: 828
Synchronize fallback model defaults across commands.
The config change to 'mistral:7b' creates inconsistency with command implementations. KnowledgeCaptureCommand uses 'mistral:7b' as its fallback (line 281), but KnowledgeSearchCommand (line 129) and QaCommand (line 257) still use 'llama3.2:3b'. When the OLLAMA_MODEL environment variable is not set, different commands will use different models. Update KnowledgeSearchCommand and QaCommand to use 'mistral:7b' as fallback to match the config default.
🤖 Prompt for AI Agents
In `@config/search.php` at line 66, The fallback model default was changed to
'mistral:7b' in config/search.php but KnowledgeSearchCommand and QaCommand still
hardcode 'llama3.2:3b', causing inconsistent behavior compared to
KnowledgeCaptureCommand; update the fallback/default model string in
KnowledgeSearchCommand and QaCommand to 'mistral:7b' (match
KnowledgeCaptureCommand and config) so all commands use the same OLLAMA_MODEL
fallback when the environment variable is unset.
Summary
know qacommand for running pint, tests, and PHPStan with optional AI fix suggestionsknow capturecommand for automatic insight extraction from conversation contextTest plan
know qa --no-airuns all checks and reports first failureknow qaprovides AI-suggested fixes via Ollamaknow capture --context="..." --dry-runshows what would be captured🤖 Generated with Claude Code
Summary by CodeRabbit
Release Notes
New Features
Improvements
✏️ Tip: You can customize this high-level summary in your review settings.