Sr. Content Developer at Microsoft, working remotely in PA, TechBash conference organizer, former Microsoft MVP, Husband, Dad and Geek.
162324 stories
·
33 followers

The Power of Polish

1 Share

Polish isn’t aesthetics, it’s protection. Rough software corrodes test, tech and trust. Learn why polish is on purpose, not just an afterthought.

Say the word “polish” and people hear “aesthetics.” The final coating. Something you add once the real work is done.

I don’t see it that way. Polish serves a purpose.

Why We Polish Metal

Think about why we polish metal in the first place.

A rough surface needs treatment, otherwise it traps moisture and dirt. That’s to prevent the metal from corroding. A polished surface is smooth, safer to handle, easier to clean and therefore it will last longer.

We don’t polish metal to make it shine. The shine is just what happens along the way.

The real reason is protection.

Fidelity Is Not Quality

In software development, it is common to create designs with sketches. These are called prototypes or low-fidelity wireframes.

Low-fidelity means the design has minimal visual detail and is usually quick and easy to make.

But somewhere along the way we started treating fidelity and quality as the same thing. Fidelity should be how much you show. Quality is how well you show it.

Low fidelity became an excuse for low quality. Quick and dirty sketches with misaligned boxes and typos. “Don’t look at the details, it’s just a wireframe.”

But people always look at the details.

My wireframes were always pixel-perfect. Sounds like a contradiction, since wireframes are supposed to be quick and rough. But an unpolished wireframe corrodes your results.

Show someone rough work, and they react to the roughness. I noticed the reaction to these imperfections became the feedback. Entire meetings derailed because of a misspelled label or inconsistent spacing.

Feedback that has nothing to do with the concept you actually wanted to test.

Polish protects that concept. Low fidelity, high quality. To me that’s not a contradiction, but a way to get results you can trust.

What Rough Software Corrodes

When low fidelity leads to lowering quality standards, you get rough software.

Rough software has serious corrosion risk worth polishing for:

Test

Put rough work in front of someone and they respond to the roughness, not the idea.

Like I mentioned, I’ve sat in reviews where a broken button or an inconsistent label hijacked the whole conversation. Everyone had opinions about the mistake. Nobody talked about the concept underneath it.

The test doesn’t find the answers you were looking for.

Tech

Unpolished increments don’t stay small.

An inconsistency here, a shortcut there. Each one looks minor by itself. But rough edges compound as the system grows. A death by a thousand cuts.

What started as a small patch becomes the pattern everyone else builds on top of. Debt paid later, with interest, instead of avoided with a bit of attention.

Trust

Trustworthiness is the big reason we should care about quality. It isn’t only about what people can see.

One misaligned label, one inconsistent flow, and people start doubting. From the part they noticed to the parts they can’t. What about the logic then? If they don’t care about this, do they care about data security? It can bring into question everything under the hood they’re trusting you got right.

Polish is about product and perception protection, about being trusted.

Beyond Software

I see the same polish pattern outside of software.

When I build a business blueprint, low fidelity by design, or a simple core story on a slide, and when the quality is there—when it’s polished—the content and intent lands.

People receive and perceive it better. It’s easier to maintain. Easier to expand later.

I recently presented a core story and brand manifesto to a client. It was a well-written paragraph, shown on a polished slide. The client actually commented that the slide showed quality and it delivered the message more strongly. It resonated.

When people trust it more, they value it more.

Purposeful polish.

The Mirror Trap

There’s one catch: you could polish forever.

Keep polishing, and metal becomes a mirror. A mirror only reflects you.

At some point polish stops protecting your software and starts serving you, the maker. You’re admiring your own craft, instead of removing noise for the user.

Polish has a purpose. And that purpose defines the boundary.

Good enough for now isn’t an excuse to ship rough work. Good enough for now still means good. You just need to know when to stop.

Closure

Forget the gloss at the end. Polish is the protection on purpose.

So don’t confuse fidelity with quality.

Do what you do well, in increments. Make it good enough for now. But make it shine.

Read the whole story
alvinashcraft
1 minute ago
reply
Pennsylvania, USA
Share this story
Delete

Goodbye, Microsoft

1 Share

A few years ago I took a new job at Microsoft, working as a Senior Content Developer, and as of this writing I own all the SQL Server content in Microsoft Docs. Not bad. After the release of ChatGPT in 2022, it was only a matter of time before large language models (LLMs) spelled the… 

The post Goodbye, Microsoft appeared first on Born SQL.

The post Goodbye, Microsoft appeared first on SQLServerCentral.

Read the whole story
alvinashcraft
1 minute ago
reply
Pennsylvania, USA
Share this story
Delete

Hello from Seattle: XBOX FanFest Comes Home November 12

1 Share

Seattle, we’re coming home. XBOX FanFest arrives at the Museum of Pop Culture (MoPOP) on Thursday, November 12, 2026, for the final stop of this year’s eight-city FanFest Tour. As we get ready to celebrate 25 years of XBOX on November 15, we’re bringing fans together in the city where it all began for a special anniversary week celebration to celebrate the games, people and memories that have shaped 25 years of XBOX

When we announced this year’s FanFest Tour, we wanted to celebrate the people who make XBOX what it is: you.

25 years of XBOX is a story we share with you. Thank you for the friendships, the enthusiasm, and the joy you bring to play. We can’t wait to mark this milestone together.

Fans joining us at MoPOP can expect a celebration of XBOX past, present and future, with hands on gameplay, XBOX history and artifacts, opportunities to connect with the people behind the games and fellow players, XBOX trivia, collectibles. fan activities, an XBOX Gear pop-up shop and plenty of surprises along the way.

Want to join us in Seattle?

We’re giving fans the chance to win their way into XBOX FanFest Seattle through the XBOX FanFest Seattle Ticket Sweepstakes. Winners will be selected at random and notified by email. Entrants and attendees must be 18 or older, and travel and lodging are not included.

Enter the XBOX FanFest Ticket Sweepstakes here.

NO PURCHASE NECESSARY. Open to eligible U.S. residents 18+. Void where prohibited. See Official Rules for eligibility, prize details, restrictions and terms. Ends October 11, 2026, at 11:59 p.m. PT.

XBOX FanFest Seattle Green Ticket Sweepstakes Image

Be our guest!

No matter where in the world you play, we want to give a lucky fan a special way to be a part of our final stop on the FanFest Tour. Enter the XBOX FanFest Green Ticket Trip Sweepstakes for a chance to win a trip for you and a friend to join us in Seattle and celebrate 25 years of XBOX together.

Enter the Green Ticket Trip Sweepstakes here. 

NO PURCHASE NECESSARY. Open to eligible residents 18+. One (1) Grand Prize consisting of a trip for winner + one (1) guest to XBOX FanFest Seattle. Void where prohibited. See Official Rules for eligibility, prize details, restrictions and terms. Ends October 11, 2026, at 11:59pm PT.

You can find more information about XBOX FanFest here. Whether you’re hoping to join us in Seattle or celebrating with your community elsewhere, visit the XBOX 25th anniversary hub to explore the wider celebration.

The post Hello from Seattle: XBOX FanFest Comes Home November 12 appeared first on XBOX Wire.

Read the whole story
alvinashcraft
1 minute ago
reply
Pennsylvania, USA
Share this story
Delete

1.0.92

1 Share

2026-10-05

  • Add copilot config subcommands to list, read, set, and remove settings.
  • Add a pre-conversation Ctrl+E environment picker to switch between local and cloud runs
  • Entra-protected MCP servers can silently renew access-token-only credentials.
  • Legacy HTTP+SSE MCP connections no longer hang indefinitely when a message POST is never acknowledged; the acknowledgement is bounded by the server's configured timeout
  • Voice runtime install errors name why the download from nuget.org failed, not only the fallback feed's 401
  • Compaction keeps your latest prompt when requests exceed context limits
  • Large Anthropic requests rejected by provider size limits now retry after downscaling images or removing attachments
  • Custom agent model entries keep model-bound reasoning effort only when that model is selected
  • Shell tool calls now stream live stdout and stderr output reliably in the timeline
  • Usage reporting preserves provider-reported reasoning token totals when available
  • Sessions no longer slow to a crawl for minutes after the agent writes a very large file in one step
  • Sandboxed shells now withhold ambient GITHUB_TOKEN unless explicitly configured.
  • Plan usage reflects the current billing period after quota resets
  • Custom agents launched through ACP task calls now resolve and run correctly
  • Remote session resume now uses your configured GitHub auth for --resume and --connect
  • Entra sign-in falls back to browser auth when no broker is available and shows a manual URL when auto-open fails
  • copilot sandbox ca commands now respect --config-dir (including with -C).
  • Search commands avoid sandbox bypass prompts when access is already granted
  • Sandboxed uv commands can write to the uv cache by default when dev tool access is enabled
  • pnpm commands run in sandboxed sessions without lock-file permission errors
  • Pressing n repeatedly in the Sessions tab reliably creates each new session
  • Reverse search updates results when command history finishes loading at startup
  • MCP tools recover within the same turn when server instructions change
  • Changing experimental mode with /experimental or /settings takes effect after restart even when launched with an opposing experimental flag
  • Keyboard, paste, and mouse input now stay ordered and responsive during rapid interaction.
  • Sandboxed shell commands offer a network bypass prompt whenever the proxy blocks a destination
  • Sandboxed scripts that run Git now authenticate with masked credentials and SSH remote rewrites
  • Sub-agents keep working after you replace your GitHub authentication credentials
  • Sandboxed commands on Windows write temporary files to the granted temp directory, so tools that rename a temp file into place work
  • Prompt-mode sessions fire a single sessionEnd hook after Stop-hook continuations complete
  • Reconnect to remote MCP servers after idle Streamable HTTP sessions expire
  • Messaging a running background agent now steers its active turn at the next processing opportunity.
  • Context rollovers keep your latest requests in the recovery context.
  • Hide the automatic sandbox CA setup prompt on Windows accounts that cannot self-elevate
  • Copilot no longer describes a subagent as configured when the current session cannot run it. Previously a session that could not use rubber-duck still reported it as set up in /subagents, and asking for it failed instead of being skipped cleanly.
  • MCP tools continue working after OAuth reauthentication when tool definitions are unchanged
  • Select which account to use after Microsoft Entra sign-in, and let /logout sign out those OAuth sessions.
  • Improve first-run startup by extracting the bundled CLI package in a child process
  • Improve startup responsiveness when connecting many MCP servers at once
  • Canvas actions can now return images to the model in invoke_canvas_action.
  • Remove retired models from the model picker and supported CLI selections
Read the whole story
alvinashcraft
2 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

# Ink comes to WinUI 3 ✍️

1 Share

Handwriting is one of those inputs that either feels instant or feels broken. There is no middle ground.

You asked for it in #7426, "Is there a plan/schedule for adding InkCanvas into WinUI desktop?", and again in #10817, when apps moving over from UWP found the control simply was not there.

It is there now. WinUI 3 has InkCanvas and InkToolbar, available from Windows App SDK 2.5.4-experimental. Between them you get a surface that collects strokes and a tool strip that drives it, so a note app stops being a drawing engine you have to write yourself.

Pen

Pen strokes in blue, red and green at increasing widths

Pencil

Pencil strokes showing graphite texture

Highlighter

Translucent highlighter bands in yellow, cyan and pink

Here is the whole thing working. One canvas, one toolbar, no custom drawing code:

Ink Notes: choosing a pen colour, drawing against the ruler stencil, writing, highlighting and sketching

A canvas is one element

InkCanvas collects strokes on its own:

<muxc:InkCanvas x:Name="Ink" />

🎨 The toolbar is the second element

InkToolbar attaches to a canvas through TargetInkCanvas:

<muxc:InkToolbar x:Name="Toolbar"
                 TargetInkCanvas="{x:Bind Ink}"
                 HorizontalAlignment="Left">
    <muxc:InkToolbarBallpointPenButton x:Name="PenButton" />
    <muxc:InkToolbarPencilButton />
    <muxc:InkToolbarHighlighterButton />
    <muxc:InkToolbarEraserButton />
    <muxc:InkToolbarStencilButton x:Name="StencilButton" />
</muxc:InkToolbar>

💾 Save a picture that is still ink

GifWithEmbeddedIsf writes an ordinary GIF with the stroke data tucked inside it, so loading the file back returns editable strokes:

// GifWithEmbeddedIsf writes a normal GIF that any viewer can open, with the stroke data
// travelling inside it. Loading the file back returns editable strokes, not a flat picture.
private async Task<int> SaveAndReloadAsync(string path)
{
    var stream = new InMemoryRandomAccessStream();
    await Ink.InkPresenter.StrokeContainer.SaveAsync(
        stream.GetOutputStreamAt(0),
        InkPersistenceFormat.GifWithEmbeddedIsf);

    var bytes = new byte[stream.Size];
    var reader = new DataReader(stream.GetInputStreamAt(0));
    await reader.LoadAsync((uint)stream.Size);
    reader.ReadBytes(bytes);

    System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(path));
    System.IO.File.WriteAllBytes(path, bytes);

    // Reload into the OS container to prove the strokes survived as ink. The WinUI
    // InkStrokeContainer has no public constructor, so use the OS one.
    var reloadStream = new InMemoryRandomAccessStream();
    var writer = new DataWriter(reloadStream.GetOutputStreamAt(0));
    writer.WriteBytes(System.IO.File.ReadAllBytes(path));
    await writer.StoreAsync();
    writer.DetachStream();

    var reloaded = new Windows.UI.Input.Inking.InkStrokeContainer();
    await reloaded.LoadAsync(reloadStream.GetInputStreamAt(0));

    return reloaded.GetStrokes().Count;
}

Attach a title bar and a page, and the two elements above are already a usable note app:

The Ink Notes sample app

The cream page and window chrome are ordinary WinUI styling around the canvas, left out of the snippets above.

The whole app

MainWindow.xaml
<?xml version="1.0" encoding="utf-8"?>
<Window
    x:Class="InkNotes.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
    Title="Ink Notes">

    <Grid x:Name="Root" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <Border Grid.Row="0"
                Margin="24,12,24,0"
                Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
                BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
                BorderThickness="1"
                CornerRadius="8"
                Padding="18,14">
            <StackPanel Spacing="12">
                <Grid>
                    <TextBlock Text="InkToolbar" FontSize="16" VerticalAlignment="Center" />
                    <Button x:Name="SaveButton"
                            Content="Save"
                            HorizontalAlignment="Right"
                            Click="OnSaveClick" />
                </Grid>
                <muxc:InkToolbar x:Name="Toolbar"
                                 TargetInkCanvas="{x:Bind Ink}"
                                 HorizontalAlignment="Left">
                    <muxc:InkToolbarBallpointPenButton x:Name="PenButton" />
                    <muxc:InkToolbarPencilButton />
                    <muxc:InkToolbarHighlighterButton />
                    <muxc:InkToolbarEraserButton />
                    <muxc:InkToolbarStencilButton x:Name="StencilButton" />
                </muxc:InkToolbar>
            </StackPanel>
        </Border>

        <Border Grid.Row="1"
                Margin="24,12,24,24"
                Background="#FFFDFCF8"
                BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
                BorderThickness="1"
                CornerRadius="8">
            <muxc:InkCanvas x:Name="Ink" />
        </Border>
    </Grid>
</Window>
MainWindow.xaml.cs
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System;
using System.Threading.Tasks;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Input;
using Windows.Storage.Streams;
using Windows.System;
using Windows.UI.Input.Inking;

namespace InkNotes
{
    /// <summary>
    /// A note page you can write on. The canvas and the toolbar do the work; this file only wires
    /// up the input devices and saving.
    /// </summary>
    public sealed partial class MainWindow : Window
    {
        public MainWindow()
        {
            this.InitializeComponent();

            // The canvas listens to pen only out of the box. Open it up to everyone.
            Ink.InkPresenter.InputDeviceTypes =
                Windows.UI.Core.CoreInputDeviceTypes.Touch |
                Windows.UI.Core.CoreInputDeviceTypes.Pen |
                Windows.UI.Core.CoreInputDeviceTypes.Mouse;

            // Ctrl+S saves too, for people who expect it.
            var save = new KeyboardAccelerator { Key = VirtualKey.S, Modifiers = VirtualKeyModifiers.Control };
            save.Invoked += async (_, args) =>
            {
                args.Handled = true;
                await SaveAsync();
            };
            Root.KeyboardAccelerators.Add(save);
        }

        private async void OnSaveClick(object sender, RoutedEventArgs e) => await SaveAsync();

        private static string NotePath => System.IO.Path.Combine(
            Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
            "InkNotes",
            "note.gif");

        private async Task SaveAsync()
        {
            int strokes = await SaveAndReloadAsync(NotePath);
            Title = $"Ink Notes - saved {strokes} strokes";
            await Task.Delay(2000);
            Title = "Ink Notes";
        }

        /// <summary>
        /// GifWithEmbeddedIsf writes a normal GIF that any viewer can open, with the stroke data
        /// travelling inside it. Loading the file back returns editable strokes, not a flat picture.
        /// </summary>
        private async Task<int> SaveAndReloadAsync(string path)
        {
            var stream = new InMemoryRandomAccessStream();
            await Ink.InkPresenter.StrokeContainer.SaveAsync(
                stream.GetOutputStreamAt(0),
                InkPersistenceFormat.GifWithEmbeddedIsf);

            var bytes = new byte[stream.Size];
            var reader = new DataReader(stream.GetInputStreamAt(0));
            await reader.LoadAsync((uint)stream.Size);
            reader.ReadBytes(bytes);

            System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(path));
            System.IO.File.WriteAllBytes(path, bytes);

            // Reload to prove the strokes survived as ink. The WinUI InkStrokeContainer has no
            // public constructor, so use the one from Windows.UI.Input.Inking.
            var reloadStream = new InMemoryRandomAccessStream();
            var writer = new DataWriter(reloadStream.GetOutputStreamAt(0));
            writer.WriteBytes(System.IO.File.ReadAllBytes(path));
            await writer.StoreAsync();
            writer.DetachStream();

            var reloaded = new InkStrokeContainer();
            await reloaded.LoadAsync(reloadStream.GetInputStreamAt(0));

            return reloaded.GetStrokes().Count;
        }
    }
}

Try it

Inking ships in the Windows App SDK experimental channel. Add Microsoft.WindowsAppSDK 2.5.4-experimental to a WinUI 3 project, add the two elements above, and you have somewhere to write.

💬 Tell us what you build

We want to hear about it: what you are building, what feels good, and anything that gets in your way. Bugs, rough edges and missing pieces are all useful to us, and the earlier they reach us the more we can do about them.

Start a discussion or file an issue at microsoft/microsoft-ui-xaml.

Happy inking 🙌

Team WinUI

Read the whole story
alvinashcraft
2 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Zero to Agent in 30 Minutes: Build Your First Agent with MCP

1 Share

Developers already have useful capabilities exposed through REST APIs. The Model Context Protocol (MCP) lets developers make those capabilities available to AI clients without rebuilding the underlying application.

In this episode of Zero to Agent in 30 Minutes, Bruce Hopkins, an AI developer, author, and longtime software educator, shows how to do that with an MCP server. His demo wraps an existing stock-data API in an MCP server so an MCP client can call it.

From REST API to MCP, step-by-step

  1. Start with an existing API. Identify the operations and data you want an AI client to access. The demo uses the Twelve Data API to retrieve current and historical stock prices.
  2. Create an MCP server. Use an MCP SDK to create the layer between the AI client and your existing application logic. In Bruce’s Python example, FastMCP handles the MCP interface while the stock-data functions remain separate.
  3. Expose capabilities as tools and resources. Register the operations the client should be able to discover and call. The stock-price data is exposed through MCP resources and tools that reuse the same underlying functions.
  4. Describe how the client should use them. Define clear names, inputs, descriptions, and prompts so the client understands what each capability does and what information it requires. Bruce’s example includes prompts for current prices, historical prices, and expected symbol and date formats.
  5. Connect the server to an MCP client. Run the server over a supported transport so the client can discover and call its tools and resources. 

You don’t need to replace the systems that already handle your application logic to help them work with agents. You can add an MCP interface around existing capabilities to give an AI client a standard way to discover and use them. Be sure to check out Bruce’s GitHub repo for working code you can adapt for your own APIs.

Coming next week

Next week, AI engineer Sajal Sharma returns to Zero to Agent in 30 Minutes to build a personal assistant on OpenClaw. He’ll show how an agent can keep tasks and notes in Markdown, run proactive automations, and deliver scheduled updates such as a regular morning briefing without waiting for a new prompt.

Follow along with Zero to Agent in 30 Minutes on Radar, or watch the latest episode on YouTube, Spotify, Apple, or wherever you get your podcasts. If you’re an O’Reilly member, you can watch live. Save your seat.



Read the whole story
alvinashcraft
3 hours ago
reply
Pennsylvania, USA
Share this story
Delete
Next Page of Stories