A private assistant does not earn trust by sounding smart. It earns trust by using the right context, performing the right action, and proving what actually happened.
This Week Was About Trust
Most of my work on Cypher this week came back to one question:
Can I trust it?
Not whether it can generate a convincing response. Not whether the interface looks impressive. Not whether another feature can be added to the list.
Can I trust Cypher to understand the situation, use the right information, perform the correct action, and prove what actually happened?
Cypher is my private personal assistant. It has to work inside my real life, not inside a clean demonstration. My schedule crosses midnight. I work twelve-hour night shifts. I train, write, build software, publish across multiple websites, handle family responsibilities, and move between subjects quickly.
A system operating inside that environment cannot treat every message like an isolated prompt.
It has to understand time. It has to apply known facts. It has to separate what I said from what it inferred. It has to know the difference between a draft and a published article. It has to recover safely when another system returns an uncertain result. It has to find the right information without pretending a partial search is a complete answer.
That was the work this week.
Not making Cypher bigger for the sake of making it bigger.
Making it more exact.
Context Has to Be Applied, Not Merely Stored
One of the first areas I worked on was how Cypher interprets daily-life information.
I use Cypher to talk through sleep, Garmin data, running, strength training, physical workload, night shift, family responsibilities, writing, and project work. Those pieces affect each other. A sleep score cannot be interpreted correctly without knowing what happened the day before, what my normal baseline looks like, whether I worked, and what I am preparing to do next.
The requirement I defined was simple:
Facts first.
Read the context.
Give the next useful move.
That changed how Cypher was instructed to interpret daily information. It was no longer enough to repeat that Garmin called my sleep “Fair.” Cypher needed to consider the run, yard work, groceries, dinner, project work, bedtime, and the fact that staying up late may be intentional preparation for night shift.
I tested the behavior the next morning.
Cypher read the sleep data, connected it to the previous day, and gave me a grounded assessment. It did not call the night a disaster. It did not repeat Garmin’s label as if the label were the entire story. It understood that I was not at full capacity, but I was stable.
That was the kind of answer I wanted.
The numbers still mattered, but they no longer existed without context.
Time Awareness Had to Match Night-Shift Reality
Time creates another problem for a personal assistant.
Cypher was already receiving the local time for America/Indiana/Indianapolis, but I needed the system to handle time more deliberately. There is a difference between the time when I send a message and the time when Cypher builds the response.
That difference matters when I use words such as “tonight,” “tomorrow,” “late,” or “after midnight.”
For someone working a normal daytime schedule, midnight may represent a clean break between days. For someone working from 5:00 p.m. to 5:00 a.m., the calendar changes while the same shift and waking block continue.
I upgraded Cypher to track both turn-start local time and response-context local time. Turn-start time helps interpret what I meant when I sent the message. Response-context time provides the current clock for the answer.
I also made the instruction explicit that calendar date alone cannot decide what words such as “tonight” or “tomorrow” mean when night shift or post-midnight context is involved.
Then I tested it directly.
I asked Cypher for the current time and date. Both answers were correct. I asked how I should handle the night before returning to night shift. Cypher understood that staying awake until around 3:00 a.m. was intentional schedule management, not automatically bad sleep hygiene.
That test confirmed the time information was not merely present in the prompt. Cypher was using it correctly.
Known Schedules Should Be Resolved Before the Model Answers
Another test exposed a related weakness.
I asked Cypher whether I was working that night.
It said it did not know.
It should have known.
Cypher already had my 2-2-3 rotation, my short-week and long-week pattern, my 5:00 p.m. to 5:00 a.m. shift, and the current date. All the pieces were available, but the system had failed to turn those pieces into an answer.
That exposed an architectural problem.
A predictable work schedule should not depend on the language model reconstructing the rotation from scattered memories every time I ask a basic question. The application should resolve the schedule first and provide the answer as structured operating context.
I added a local schedule resolver.
The schedule is now stored as structured configuration:
Short week: Wednesday and Thursday.
Long week: Monday, Tuesday, Friday, Saturday, and Sunday.
Shift: 5:00 p.m. to 5:00 a.m.
Anchor: Monday, July 6, 2026, as the beginning of a short week.
From that anchor, Cypher can calculate the rotation without guessing. It can determine whether I am scheduled to begin a shift that evening, whether I am still inside a shift that started the previous evening, and when my next regular shift begins.
Temporary changes can override the normal pattern. Overtime, leave, boat patrol, shift swaps, and other confirmed changes still take priority.
I repeated the original test.
“Am I working tonight?”
Cypher correctly answered that I was off and that my next regular shift began Monday, July 13, at 5:00 p.m.
The information had been there before.
The difference was that Cypher now had a reliable way to apply it.
Memory is not enough. A useful assistant has to resolve what it knows into the answer the situation requires.
Model Controls Needed Proof Behind Them
I also improved the controls governing which OpenAI model Cypher uses.
Cypher already allowed model selection, but the model name was only one part of the configuration. Reasoning level also mattered, and I wanted the two controls separated.
More importantly, I wanted evidence that the API used what the interface claimed it used.
A dropdown can display anything. That does not prove what happened after the request left the application.
I added separate model and reasoning controls, defined fallback behavior, and expanded response metadata. Cypher now records the requested model, the model returned by OpenAI, the reasoning level, whether fallback was used, and the response ID.
I tested the first implementation through the database using GPT-5.5 with medium reasoning. The stored response confirmed that GPT-5.5 had been requested and used, medium reasoning was active, and no fallback had occurred.
When GPT-5.6 became available to my API account, I extended the same system. I added the available GPT-5.6 options and changed Cypher to GPT-5.6 Terra with medium reasoning. GPT-5.5 remained the fallback because it had already been proven inside the system.
The next database check confirmed:
GPT-5.6 Terra requested.
GPT-5.6 Terra used.
Medium reasoning.
No fallback.
The model was not merely selected in the interface. It was running.
That distinction matters throughout this project. I do not want settings that look correct. I want behavior I can verify.
Memory Needed Provenance, Corrections, and Receipts
The largest reliability problem involved memory.
Cypher could take something I said, normalize it into a cleaner summary, and later treat that summary as if it were my exact statement. That creates several risks.
A relative reference to time can become attached to the wrong week. An assistant interpretation can return later sounding like a direct quote. A correction can be stored beside the original record, leaving both versions active. A save confirmation can appear even when persistence was never verified.
The issue was not whether Cypher could remember information.
The issue was whether I could trust the memory after it had been processed.
I defined several requirements.
Cypher needed to preserve my original wording separately from its normalized interpretation. It needed to record provenance, confidence, ambiguity, and temporal scope. It needed to distinguish direct statements from assistant inference. Corrections needed to supersede old records instead of creating two competing facts.
It also needed to stop claiming that something was saved merely because it understood what I said.
A memory save now has to complete the database write, read the record back, and verify persistence before Cypher can honestly confirm that the information was stored.
I added regression coverage around the failure points, including plans versus completed events, relative time, conflicting records, corrections, unsupported inference, and failed writes.
This changed memory from a collection of convenient summaries into a more accountable record system.
Cypher can still interpret what I say. It just cannot quietly replace what I said with its interpretation.
Publishing Needed an Active Draft, Not Just Good-Looking Text
Publishing exposed a different kind of state problem.
The original workflow was straightforward. I could ask Cypher to write a Bonumark Stream post, review the local draft, and approve it by saying, “publish that post.” I could also supply exact text with a direct command and have it published without rewriting.
The failure appeared when I revised a draft.
Cypher could create the first version correctly, but a follow-up instruction, such as “make it longer,” “remove that section,” or “change the ending” produced an ordinary assistant response. The new text appeared in the conversation, but it did not become the active publishable draft.
That meant the version I was reading and the version eligible for publication could be different.
I changed the workflow to maintain an active draft state.
Follow-up editing instructions now remain inside the drafting process. Every successful revision becomes the new active version. The previous version is marked as superseded. Only the latest active draft can be published.
I tested the complete path with a real post.
Cypher wrote the first version. I asked it to make the post slightly longer. It returned a full revision and registered it as the active Bonumark draft. I approved the post, and the revised version went live.
That confirmed the workflow I actually need:
Write the post.
Revise the post.
Publish the final version.
Remote Uncertainty Could Not Be Allowed to Create Duplicates
Publishing to another system introduces uncertainty.
A remote service can successfully create a post while Cypher loses the response. From Cypher’s perspective, the request may appear to have failed even though the post is already public.
A blind retry could then create a duplicate.
I added an explicit uncertain publication state for that situation.
When a timeout happens after a possible remote write, Cypher no longer treats it as an ordinary failure. It preserves the original idempotency key, records the uncertain result, and retries the same operation. Bonumark can then recognize the request and return the existing post instead of creating another one.
I built an end-to-end regression around that exact sequence.
The test created the remote post, interrupted the response, preserved the request identity, retried safely, recovered the existing public post, prevented a duplicate, and reconciled the local draft as published.
That is not the kind of feature anyone notices when everything works.
It is the kind of protection that matters when something goes wrong.
Publishing Commands Had to Understand Real Language Without Guessing
Another publishing issue came from the command parser.
I supplied text and mistyped “publish” as “publis.” Cypher did not route the message to the direct publishing path. I followed with, “dude I said publish this,” and it still failed because the detector expected the command to begin in a narrow, exact format.
The publishing system itself was working. The command detector was too brittle for normal use.
I expanded it to understand obvious command variations such as “publis this,” “please publish this,” “dude, I said publish this,” and “publish this as-is.”
At the same time, I kept the safety boundary.
Cypher should not publish because I ask, “Should I publish this?” It should not publish without actual content. It should not guess that discussion about publishing is authorization to publish.
That balance became even more important when I pasted a long project summary into the conversation. The pasted material contained old phrases about writing and revising posts. Because an unpublished draft still existed, the classifier found those buried phrases and treated the entire summary as an editing request.
I had not asked it to revise anything.
I tightened both the revision and new-post classifiers. Publishing intent now has to be the actual instruction, not a command-like phrase buried inside notes, logs, quoted text, or a pasted conversation.
The exact false-positive structure became a regression case.
Normal commands still work. Pasted material remains context unless I directly instruct Cypher to use it.
The Chat Workspace Had to Behave Like the Tool I Use Every Day
Reliability also includes the interface.
Cypher’s chat screen had the correct basic pieces, but it still felt more like a custom administrative panel than a private assistant I use throughout the day. The sidebar was heavy. Conversation rows looked like large cards. Message counts added noise. The main workspace carried too much blue-gray paneling. New conversations opened with the composer at the bottom instead of placing the prompt where attention naturally begins.
I used the design language of modern AI chat tools as a reference without trying to copy one of them.
The sidebar became narrower and more neutral. Conversation rows became simpler. Message counts were removed. Memory, Settings, Usage, Backups, Upgrade, and Sign out were organized inside the Jim account area. Desktop gained a collapse control, while mobile kept a focused overlay.
New conversations now open with Cypher’s gold mark, a direct prompt, and the composer centered higher in the workspace. Once the conversation begins, the composer returns to the bottom.
User messages sit in right-aligned bubbles. Cypher’s responses remain open and readable. Repeated role labels were removed. The composer, attachment control, and privacy note were simplified.
Then the interface testing exposed a problem that mattered more than the visual cleanup.
On desktop reload, Cypher would begin moving toward the newest message and then jump backward into older history.
The code already contained a startup scroll-to-bottom function. That did not mean the interaction worked.
Persistent smooth scrolling was turning the initial position into an animation. As the scroller moved through the history threshold, Cypher could mistake its own programmatic movement for the user scrolling upward. That triggered older-message loading, preserved the wrong position, and pulled the conversation back.
I removed persistent smooth behavior from the message scroller, kept smooth movement only for intentional new-message scrolling, blocked history loading while the page was settling, and required actual upward movement before older history could load automatically.
I also added a desktop correction for the browser, restoring a nested scroll position after reload, while leaving the working mobile path alone.
The dedicated test forced a long conversation into a partial position, reloaded it on desktop and mobile, and verified that Cypher finished at the newest message without requesting older history during startup.
That test checked the behavior I experience, not merely the presence of a scroll function.
Visual work is not only visual. Layout, timing, history loading, browser restoration, and user movement can collide inside one interaction.
A clean screenshot would not have caught that.
Using Cypher did.
Cache Optimization Needed Measurement
I also worked on the cost and visibility of Cypher’s OpenAI requests.
Usage data showed a large number of cache-write tokens and no cache reads. Cypher was paying to create cached prompt material without reusing it.
The reason became clear when I inspected how requests were assembled.
Permanent operating instructions and constantly changing information were combined into one large instruction block. Current time, retrieved memories, recent conversation history, evidence records, and daily context changed from request to request. Because all of that sat inside the same prefix, the cache could not remain stable.
Cutting context would have solved the wrong problem.
I wanted Cypher to keep its awareness while making the reusable part of the prompt truly reusable.
I separated the request into stable and dynamic sections. Permanent instructions and operating rules now form the stable prefix. Current time, memory retrieval, evidence, conversation history, and the latest request remain dynamic.
Cypher now creates a versioned cache key and records a stable-prefix hash so matching requests can be verified.
I also added local telemetry for token use, cache reads, cache writes, uncached input, model, reasoning level, response time, fallback behavior, cache key, and stable-prefix hash. Prompt text is not stored in that telemetry.
The first live test produced measurable results.
The first eligible request wrote 1,494 tokens into the cache. The next three requests used the same cache key and stable-prefix hash. Each read those 1,494 tokens instead of writing them again.
Across the four requests, Cypher recorded 1,494 cache-write tokens and 4,482 cache-read tokens. That produced a three-to-one read-to-write ratio and a 75 percent hit rate among eligible requests.
Memory-extraction requests remained uncached by design because they do not share the main stable prefix.
The test proved that changing time, conversation content, and retrieved memory no longer invalidated Cypher’s permanent instructions.
Visibility Had to Become Usable
The first telemetry page technically showed the information, but it looked like a diagnostic dump.
Summary values ran together. Cache identifiers wrapped badly. The request table was cramped. The reported hit rate included requests that were never eligible for the shared cache.
I changed the requirement.
The goal was no longer to display the data. The goal was to make the data useful while administering Cypher.
The rebuilt Usage page now includes summary cards, cache-health information, eligible-request hit rates, readable purpose and model labels, date-range controls, and expandable request details.
That visual system was then applied across Memory, Settings, Backups, and Upgrade.
Memory gained clearer separation between imports, evidence, corrections, receipts, and recent changes. Settings was divided into focused sections for time, schedule, models, publishing, memory, reliability, and sign-in controls. Backups gained file availability, verification status, size information, and clearer restore controls. Upgrade gained clearer protection steps and history results.
The interface pass also exposed smaller problems.
The Usage page was missing from the account menu. Administrative links were sitting above the user area instead of inside it. The “Load earlier messages” control appeared inside a brand-new empty conversation because a CSS display: flex rule overrode the server-rendered hidden state.
I corrected those details and added regression coverage.
Small errors matter because they change how trustworthy the whole system feels.
Cypher Needed Access to the Work I Had Already Published
The largest capability added this week was a knowledge and publishing system for JimLunsford.com.
Before this work, Cypher could remember personal context, but it could not reliably search the years of work I had already published. It did not have structured access to my Recovery Standards, Discipline Dispatches, Builder Receipts, frameworks, long-form articles, or permanent website pages.
I did not want that material treated as ordinary personal memory.
A published article is a source document. It has a title, URL, publication date, content, version, origin, category, and content hash. It needs different rules from a remembered fact about my schedule or daily life.
I created a dedicated writing knowledge system and synchronized 141 published WordPress posts from JimLunsford.com.
Cypher stores the original WordPress content, a cleaned search version, titles, URLs, dates, categories, tags, headings, links, WordPress IDs, and content hashes. Repeated synchronization updates existing records instead of creating duplicates. Removed or unavailable content is marked for review instead of being silently deleted.
The first synchronization caught another state problem.
The articles imported correctly, but the synchronization still appeared to be running. The content was present while the run record remained unfinished.
I traced the difference between the imported records and the stuck synchronization state, then corrected the bookkeeping.
A system that performs the work but reports the wrong state is still unreliable.
Search Needed Sources and Clear Boundaries
Once the documents were stored, I added keyword search, semantic search, exact title matching, quoted phrase matching, category filters, content-type filters, source cards, and citation markers.
The requirement was straightforward.
When Cypher says I wrote something, it has to retrieve the source that proves it.
It cannot generate an idea that sounds like me and then present that generated language as something I previously published.
Published knowledge, current statements, assistant interpretation, and personal memory remain separate. What I say now takes priority over an older article. A published article proves what I wrote at that time. It does not automatically prove I still hold the same position today.
I also added controls for how published writing enters a conversation: Auto, Always, and Off. Direct instructions can force or block retrieval when needed.
That allows Cypher to use my work naturally without dragging old articles into every conversation.
Drafts and WordPress Needed Their Own Provenance
Cypher can now use published sources to compare ideas, identify overlap, suggest internal links, find repeated arguments, build briefs, create outlines, and develop complete drafts.
The key requirement was provenance.
A generated draft is not a published article. It is not personal memory. It is not evidence that I wrote those exact words before.
Drafts have their own records, revision history, source trail, and status. New revisions become active. Older revisions become superseded. The published sources used to support the work remain attached.
I then connected the workflow to WordPress.
Cypher can create a WordPress draft, update that same draft after revisions, publish only after explicit authorization, read the WordPress record back, verify what was stored, and synchronize the published article into the knowledge library.
The publishing commands remain separate.
“Publish that post” is for Bonumark Stream on JimLunsford.net.
“Create a WordPress draft,” “Update the WordPress draft,” and “Publish the article” control the JimLunsford.com workflow.
I tested the full path with a disposable article.
That test exposed type handling around a year in the title, an exclusion instruction that was ignored when it appeared later in the prompt, duplicate-draft concerns, stale local revisions, and WordPress content normalization.
The backup records eventually showed the actual state.
WordPress had revision one.
Cypher had revision two.
The new paragraph had not yet been sent to WordPress.
Cypher was correct to block publication.
I updated the WordPress draft, published the article, verified the live result, and found the article through Cypher’s knowledge search.
The complete workflow worked.
I also added a Help page documenting the Bonumark Stream and WordPress commands with copy controls. I should not need to memorize every command while learning and refining a workflow I built.
The knowledge synchronization was later expanded to include 12 permanent WordPress pages as read-only sources. Pages can be searched, cited, and used during article development, but Cypher cannot create, modify, or publish them.
That boundary is intentional.
The Right Information Still Requires the Right Query
The knowledge library passed its publishing and retrieval tests, but a basic question exposed another weakness.
I asked Cypher how many Recovery Standards I had published.
It said it could confirm at least six.
The library was complete. The problem was not missing content.
Cypher had treated an inventory question like a semantic-search question. Semantic retrieval is designed to find the most relevant passages. It is not designed to return every document in a collection or calculate an authoritative total.
Cypher had counted the limited passages selected for the conversation instead of querying the complete synchronized catalog.
When I challenged the answer, it acknowledged that the result was partial but continued using the same limited retrieval path. It also attached unrelated article sources that did not support the count.
The system had access to the answer.
It was using the wrong tool.
I separated thematic retrieval from collection inventory.
“Have I written about resilience?” should use semantic and keyword search.
“How many Recovery Standards have I published?” should query the complete document catalog.
The inventory path now handles totals, complete lists, first and latest entries, publication dates, document types, series membership, and time-based counts.
The synchronized catalog contained 46 posts in the Recovery Standards category, but one was the series introduction, “Start Here: What Are Recovery Standards?”
The correct number of actual Recovery Standard entries was 45.
I turned the failure into a regression case and tested the finished upgrade against the real backup, not just a small fixture.
Cypher then gave the complete answer, explained why the category contained 46 posts, identified the series introduction, and stated that the result came from the latest synchronized catalog.
That was the answer the system should have given the first time.
The fix was not to make Cypher sound more confident.
The fix was to give it an authoritative query path and require that path when the question demands a complete answer.
What This Week Proved
This week was not one prompt producing a finished system.
I found problems by using Cypher inside my actual life.
I defined the behavior I expected.
I separated responsibilities that should not have been combined.
I turned failures into regression cases.
I inspected database records, telemetry, browser behavior, synchronization states, backups, publishing records, API responses, and live results.
I verified model use instead of trusting the selector.
I resolved schedules in the application instead of hoping the model calculated them correctly.
I separated original statements from normalized memory.
I required database readback before save confirmation.
I created active draft state instead of trusting whichever version happened to be visible in chat.
I protected remote publishing with idempotent recovery.
I tightened command detection without letting Cypher guess its way into publishing.
I tested the interface through real reload behavior.
I changed prompt architecture and measured the cache result.
I gave Cypher access to my published work without confusing sources, memories, drafts, and generated language.
I taught it the difference between finding relevant documents and measuring the complete collection.
The common thread through all of it was accountability.
A response sounding right is not enough.
A setting appearing selected is not enough.
A draft looking finished is not enough.
An API saying success is not enough.
A search finding six relevant articles is not enough when the question asks for the complete count.
The system has to prove what it used, what it did, what it stored, and what happened next.
That is how I am building Cypher.
Not as a public product.
Not as a demonstration.
As a private personal assistant that has to keep up with my actual life and earn trust through the way it behaves.
This week, it got much better at doing that.